1 /*
2 并查集(Union-Find)裸题
3 并查集三个函数:初始化Init,寻找根节点Find,连通Union
4 考察:连通边数问题
5 */
6 #include <cstdio>
7 #include <algorithm>
8 #include <cstring>
9 #include <cmath>
10 using namespace std;
11
12 const int MAX_N = 1000 + 10;
13 int pre[MAX_N];
14 int tot;
15
16 int find(int root)
17 {
18 int son, tmp;
19 son = root;
20
21 while (root != pre[root])
22 {
23 root = pre[root];
24 }
25 while (son != root) //路径压缩 非递归版
26 {
27 tmp = pre[son];
28 pre[son] = root;
29 son = tmp;
30 }
31
32 return root;
33 }
34
35 void joint(int root1, int root2)
36 {
37 int x, y;
38
39 x = find (root1);
40 y = find (root2);
41
42 if (x != y)
43 {
44 pre[x] = y;
45 tot--; //连通一条少一条边
46 }
47 }
48
49 int main(void) //HDOJ 1232 畅通工程
50 {
51 //freopen ("inA.txt", "r", stdin);
52 int n, m;
53 int x, y;
54
55 while (~scanf ("%d%d", &n, &m) && n)
56 {
57 for (int i=1; i<=n; ++i)
58 {
59 pre[i] = i;
60 }
61 tot = n - 1; //tot 记录边 (n个顶点有n-1条边)
62 while (m--)
63 {
64 scanf ("%d%d", &x, &y);
65 joint (x, y);
66 }
67 printf ("%d\n", tot); //还有几条边(路)没有连通
68 }
69
70 return 0;
71 }