Algorithm Design——并查集

 1  /**
 2 并查集定义:
 3 并查集是一种树形数据结构,用于实现如确定某个集合含有哪些元素、判断
 4 某两个元素是否存在于同一个集合中、求集合中元素的数量等问题。
 5 并查集主要操作:
 6 (1)合并两个不相交的集合;
 7 (2)判断两个元素是否属于同一集合。
 8 
 9 题目描述: 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直
10 接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(
11 但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设
12 多少条道路? 
13 输入:
14 测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别
15 是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出 
16 一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从
17 1到N编号。当N为0时,输入结束,该用例不被处理。
18 输出:
19 对每个测试用例,在1行里输出最少还需要建设的道路数目。
20 样例输入: 
21 4 2 
22 1 3 
23 4 3 
24 3 3 
25 1 2 
26 1 3 
27 2 3 
28 5 2 
29 1 2 
30 3 5
31 999 0 
32 0
33 样例输出: 
34 1 
35 0 
36 2
37 998
38 */
39 
40 #include<cstdio>
41 using namespace std;
42 
43 #define N 1000
44 
45 int Tree[N];
46 //查找某个节点所在树的根节点
47 int findRoot(int x)
48 {
49     if(Tree[x] == -1)
50         return x;
51     else
52     {
53         int tmp = findRoot(Tree[x]);
54         Tree[x] = tmp;
55         return tmp;
56     }
57 }
58 
59 int main()
60 {
61     int n, m;
62     while(scanf_s("%d", &n) != EOF && n != 0)
63     {
64         scanf_s("%d", &m);
65         //初始时,所有节点都是孤立的集合,即其所在集合只有一个节点,其本身就是所在树的根节点
66         for(int i = 1 ; i <= n ; i ++)
67             Tree[i] = -1;
68 
69         while(m -- != 0)//读入边信息
70         {
71             int a, b;
72             scanf_s("%d%d", &a, &b);
73             a = findRoot(a);
74             b = findRoot(b);//查找两个顶点所在的集合信息
75             if(a != b)
76                 Tree[a] = b;//若两个顶点不在同一个集合,则合并这两个集合
77         }
78 
79         int ans = 0;
80         for(int i = 1 ; i <= n ; i ++)
81         {
82             if(Tree[i] == -1)
83                 ans ++;//统计所有节点中根节点的个数
84         }
85 
86         printf_s("%d
", ans - 1);//ans-1即是所修道路的最小个数
87     }
88 
89     return 0;
90 }
原文地址:https://www.cnblogs.com/yiyi-xuechen/p/3452304.html