题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4463思路:由于nike与apple必须有直接的边相连,因此可以先把这条边选进去,然后就是Kruskal求最小生成树了,由于一开始已经把点nike和点apple合并了,因此kruskal选择边的时候就不会选进去了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 struct Node{ 8 int x,y; 9 }node[55]; 10 struct Edge{ 11 int u,v; 12 double len; 13 }edge[55*55]; 14 int parent[55]; 15 int n; 16 17 int Find(int x){ 18 int s; 19 for(s=x;parent[s]>=0;s=parent[s]) 20 ; 21 while(x!=s){ 22 int tmp=parent[x]; 23 parent[x]=s; 24 x=tmp; 25 } 26 return s; 27 } 28 29 void Union(int R1,int R2){ 30 int r1=Find(R1),r2=Find(R2); 31 if(r1==r2)return ; 32 if(parent[r1]<parent[r2]){ 33 parent[r1]+=parent[r2]; 34 parent[r2]=r1; 35 }else { 36 parent[r2]+=parent[r1]; 37 parent[r1]=r2; 38 } 39 } 40 41 double Get_Dist(int x1,int y1,int x2,int y2){ 42 int dd=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); 43 return sqrt(dd*1.0); 44 } 45 46 int cmp(const Edge &p,const Edge &q){ 47 return p.len<q.len; 48 } 49 50 51 int main(){ 52 // freopen("1.txt","r",stdin); 53 int p,q,k; 54 double ans; 55 while(~scanf("%d",&n)&&n){ 56 scanf("%d%d",&p,&q); 57 for(int i=1;i<=n;i++){ 58 scanf("%d%d",&node[i].x,&node[i].y); 59 } 60 ans=k=0; 61 for(int i=1;i<=n;i++){ 62 for(int j=i+1;j<=n;j++){ 63 edge[++k].u=i; 64 edge[k].v=j; 65 edge[k].len=Get_Dist(node[i].x,node[i].y,node[j].x,node[j].y); 66 if(i==p&&j==q)ans=edge[k].len; 67 } 68 } 69 sort(edge+1,edge+1+k,cmp); 70 memset(parent,-1,sizeof(parent)); 71 Union(p,q); 72 for(int i=1;i<=k;i++){ 73 int u=Find(edge[i].u); 74 int v=Find(edge[i].v); 75 if(u!=v){ 76 ans+=edge[i].len; 77 Union(u,v); 78 } 79 } 80 printf("%.2lf\n",ans); 81 } 82 return 0; 83 }