1. 程式人生 > >Aizu-2224Save your cats並查集+最小生成樹

Aizu-2224Save your cats並查集+最小生成樹

truct tdi cat 題意 生成 ats you col for

Save your cats

題意:存在n個點,有m條邊( input中讀入的是 邊的端點,要先轉化為邊的長度 ),做一個最小生成樹,使得要去除的邊的長度總和最小;

思路:利用並查集和求最小生成樹的方法,註意這裏的排序要從大到小排,這樣最後建樹的消耗最大,反過來去除的最小;

當然題意不是這麽直白,感覺以後看到要做一個不成環的圖時,要想到最小生成樹;

下面是ac代碼:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include 
<cmath> const int maxn =10007; const int mx =2e6+7; using namespace std; int n,m,fa[maxn]; struct node { int from; int to; double r; }a[mx]; struct nn{ int x,y; }p[maxn]; bool cmp(node a,node b) { return a.r>b.r; //這裏的判斷用大於,使得sort從大到小排列 } void init(){
for(int i=1;i<=n;i++) fa[i] = i; memset(a,0,sizeof(a)); memset(p,0,sizeof(p)); } int find(int x) { if(fa[x]==x)return x; else return fa[x] = find (fa[x]); } bool uni(int x,int y) { int px = find(x); int py = find (y); if(px==py)return false; fa[px] = py;
return true; } int main(){ scanf("%d%d",&n,&m); init(); for(int i=1;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); p[i].x=x; p[i].y=y; } double sum = 0,res=0; for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); double tmp = sqrt((p[u].x-p[v].x)*(p[u].x-p[v].x)+(p[u].y-p[v].y)*(p[u].y-p[v].y)); a[i].from=u; a[i].to=v; a[i].r = tmp; sum+=tmp; } sort(a+1,a+1+m,cmp); for(int i=1;i<=m;i++) { int u = a[i].from; int v = a[i].to; if(uni(u,v))res+=a[i].r; } printf("%.3lf\n",sum-res); return 0; }

Aizu-2224Save your cats並查集+最小生成樹