- 亲戚题:已知a和b是亲戚,a和c是亲戚,则可以判断出b和c也是亲戚。
- 将多个集合合并成没有交集的集合。
1 #include <iostream>
2 using namespace std;
3
4 int N, M, Q;
5 int pre[20000], rak[20000];
6
7 void MakeSet(int x)
8 {
9 pre[x] = -1;
10 rak[x] = 0;
11 }
12
13 int FindSet(int x)
14 {
15 int r = x, q;
16 while (pre[r] != -1)
17 r = pre[r]; //此时r是代表节点
18 while (x != r) //路径压缩
19 {
20 q = pre[x];
21 pre[x] = r; //将r作为所有非根节点的父节点
22 x = q;
23 }
24 return r;
25 }
26
27 void UnionSet(int a, int b)
28 {
29 int t1 = FindSet(a);
30 int t2 = FindSet(b);
31 if (rak[t1] > rak[t2])
32 pre[t2] = t1;
33 else
34 pre[t1] = t2;
35 if (rak[t1] == rak[t2])
36 rak[t2]++;
37 }
38
39 int main()
40 {
41 int i, a, b, m, n;
42 while (cin >> N >> M)
43 {
44 for (i = 1; i <= N; i++)
45 MakeSet(i);
46 for (i = 1; i <= M; i++)
47 {
48 cin >> a >> b;
49 if (FindSet(a) != FindSet(b))
50 UnionSet(a, b);
51 }
52 cin >> Q;
53 for (i = 1; i <= Q; i++)
54 {
55 cin >> m >> n;
56 if (FindSet(m) != FindSet(n))
57 cout << m << ' ' << n << " No" << endl;
58 else
59 cout << m << ' ' << n << " Yes" << endl;
60 }
61 }
62 }