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\n", ans - 1);//ans-1即是所修道路的最小个数
87 }
88
89 return 0;
90 }