HDU 1875 畅通工程再续 最小生成树问题
题目描述:输入一个T,表示有T组测试数据,然后每组测试数据有一个C,表示在一个湖里面有C座岛屿,现在要在岛屿之间修建桥,可以修建必须满足的条件是岛与岛之间的距离在10到1000的范围内,然后给出每座岛屿的坐标,并且每米的修建桥的费用为100,求能把所有岛屿连接起来的所需要的最小费用,如果不能将所有的岛屿联通,则输出oh?
解题报告:比较裸的一道最小生成树,因为有一个判断到底是否存在最小生成树的问题,所以,个人觉得用克鲁斯卡尔比较好,因为要用到并查集,那样就不用再另外写一个并查集了。直接看代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 const int MAX = 100+5; 5 double map[MAX][MAX],loc[MAX][2]; 6 struct node { 7 int x,y; 8 double length; 9 }rode[MAX]; 10 bool cmp(node a,node b) { //比较函数 11 return a.length<b.length; 12 } 13 int T,C,prim[MAX]; 14 double distan(double x1,double y1,double x2,double y2) { //求两岛屿之间的距离 15 return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); 16 } 17 int find(int k) { //并查集 18 return prim[k]==k? k:prim[k] = find(prim[k]); 19 } 20 int main() { 21 scanf("%d",&T); 22 while(T--) { 23 scanf("%d",&C); 24 for(int i = 1;i<=C;++i) 25 scanf("%lf%lf",&loc[i][0],&loc[i][1]); 26 int k = 0; 27 for(int i = 1;i<=C;++i) 28 for(int j = i+1;j<=C;++j) { //将距离转换成边 29 double dis = distan(loc[i][0],loc[i][1],loc[j][0],loc[j][1]); 30 if(dis<=1000&&dis>=10) 31 rode[++k].x = i,rode[k].y = j,rode[k].length = dis; 32 } 33 std::sort(rode+1,rode+k+1,cmp); 34 double sum = 0; 35 for(int i = 1;i<=C;++i) 36 prim[i] = i; 37 for(int i = 1;i<=k;++i) 38 if(find(rode[i].x)!=find(rode[i].y)) { 39 prim[find(rode[i].x)] = find(rode[i].y); 40 sum+=rode[i].length; 41 } 42 bool flag = 0; 43 for(int i = 2;i<=C;++i) //判断是否存在最小生成树 44 if(find(1)!=find(i)) { 45 flag = 1; 46 break; 47 } 48 if(flag) { 49 printf("oh!\n"); 50 continue; 51 } 52 printf("%.1lf\n",100.0*sum); 53 } 54 return 0; 55 } 56