并查集
- 亲戚题:已知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 }