hdu 1233 还是畅通工程 解题报告

题目链接:http://code.hdu.edu.cn/showproblem.php?pid=1233

     并查集的运用, 实质就是求最小生成树。先对所有的村庄距离从小到大排序,然后判断村庄之间是否属于同一集合,不是则将距离相加。属于同一集合,说明村庄连成了环,就不符合树的定义了。这样扫描下来,就求得最小生成树了。

     要特别注意的是,数组越界问题。这个得益于Dwylkz的指点。由于村庄最多假设为100,为了防止边数越界,数组应该开到100 * 100 (10000)左右。

   

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int maxn = 10000 + 10;    // 100个村庄边数最多为10000
 6 struct sets
 7 {
 8     int v1, v2;   // v1,v2分别表示村庄1和村庄2
 9     int value;    // 保存两村庄间的距离
10 } test[maxn];
11 
12 int set[maxn];     // 保存集合中的代表
13 
14 int cmp(sets a, sets b)
15 {
16     return a.value < b.value;
17 }
18 
19 int find(int x)
20 { 
21     return x == set[x] ? x : find(set[x]);
22 }
23 
24 int main()
25 {
26     int a, b, i, n, cnt;
27     while (scanf("%d", &n) != EOF && n)
28     {
29         for (i = 1; i <= n; i++)
30         {
31             set[i] = i;   // 初始化为n个不相交的集合
32         }
33         int len = n * (n-1) / 2;    // 输入的行数
34         for (i = 0; i < len; i++)
35         {
36             scanf("%d%d%d", &test[i].v1, &test[i].v2, &test[i].value);
37         }
38         sort(test, test+len, cmp);   // 对距离从小到大排序
39         for (cnt = i = 0; i < len; i++)
40         {
41             a = find(test[i].v1);
42             b = find(test[i].v2);
43             if (a != b)      // 不属于同一集合,则将距离相加,这个已保证能得到最小生成树
44             {
45                 set[a] = b;
46                 cnt += test[i].value;
47             }
48         }
49         printf("%d\n", cnt);
50     }
51     return 0;
52 }

 

 

posted @ 2013-09-08 12:00  windysai  阅读(175)  评论(0编辑  收藏  举报