题目:http://acm.hdu.edu.cn/showproblem.php?pid=1875
分析:kruskal算法。先确保每个岛都有至少一条有效边与其他岛相连,然后直接kruskal即可。(但我出现了很意外的错误,在ide上如果用C++11之前会出现很神奇的错误,之后就没有,在vjudge上用C++不行,但G++可行。。)
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 struct edge 7 { 8 int u,v; 9 double w; 10 }e[110000]; 11 struct point 12 { 13 int x,y; 14 }p[110]; 15 int t,n,f[110],cnt,tot; 16 double ans; 17 int find(int k) 18 { 19 if(f[k]==k)return k; 20 return f[k]=find(f[k]); 21 } 22 double cmp(edge a,edge b) 23 { 24 return a.w<b.w; 25 } 26 double distance(int i,int j) 27 { 28 return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y)); 29 } 30 void add(int u,int v,double w) 31 { 32 e[++cnt].u=u; 33 e[cnt].v=v; 34 e[cnt].w=w; 35 } 36 int main(void) 37 { 38 scanf("%d",&t); 39 while(t--) 40 { 41 tot=cnt=0; 42 ans=0; 43 int b=0; 44 scanf("%d",&n); 45 for(int i=1;i<=n;i++) 46 { 47 scanf("%d %d",&p[i].x,&p[i].y); 48 f[i]=i; 49 } 50 for(int i=2;i<=n;i++) 51 { 52 int p=0; 53 for(int j=1;j<i;j++) 54 { 55 double d=distance(i,j); 56 if(d<=1000&&d>=10) 57 { 58 add(i,j,d); 59 p=1; 60 } 61 } 62 if(p==0) 63 { 64 printf("oh! "); 65 b=1; 66 break; 67 } 68 } 69 if(b==1)continue; 70 sort(e+1,e+1+cnt,cmp); 71 for(int i=1;i<=cnt;i++) 72 { 73 int fu=find(e[i].u),fv=find(e[i].v); 74 if(fu==fv)continue; 75 f[fu]=fv; 76 ans+=e[i].w; 77 if(++tot==n-1)break; 78 } 79 printf("%.1f ",ans*100); 80 } 81 return 0; 82 }