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             
View Code

 

posted @ 2013-07-30 20:01  xiaxiaosheng  阅读(281)  评论(0编辑  收藏  举报