扩展域并查集 || P1892 [BOI2003]团伙

https://www.luogu.com.cn/problem/P1892
本题涉及扩展域并查集。
所谓扩展域并查集其实就是一个并查集存储了多个属性,以此题为例,p[x]存储了x的朋友是谁,p[x + n]存储x的敌人是谁,以此为扩展p[x + a * n]代表x的第a个属性,可以理解为用空间来存储属性(但是我目前的理解只局限于朋友和敌人这道题)。需要注意的是存储多个属性的时候要双向存储(p[find(a + n)] = p[find(b)], p[find(b + n)] = p[find(a)])(目前还不清楚是共性还是这道题目的属性,可以暂时从这个题目理解一下,因为两个关系之间有相互作用的关系,所以存储的时候本质还是维护一个并查集,所以要双向存储),大抵是这道题目的属性因为从另一个角度想同时也可以用p[a] 和 p[a + n] 同时维护两个并查集,并且这时候不双向存储的话就纯纯维护了两个完全不相关的并查集,类似于例题https://www.luogu.com.cn/problem/P2078,下面也会放上源码。
代码 :
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define gogo ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL); 4 const string YES = "Yes"; 5 const string NO = "No"; 6 7 const int N = 30010; 8 int p[N]; 9 int n, m, s, q; 10 int find(int x) { 11 if (p[x] != x) p[x] = find(p[x]); 12 return p[x]; 13 } 14 int32_t main() { 15 gogo; 16 cin >> n >> m >> s >> q; 17 for (int i = 1;i <= n + m;i ++) 18 p[i] = i; 19 while (s --) { 20 int x, y; 21 cin >> x >> y; 22 if (find(x) != find(y)) 23 p[find(x)] = find(y); 24 } 25 while (q --) { 26 int x, y; 27 cin >> x >> y; 28 x = -x, y = -y; 29 if (find(x + n) != find(y + n)) 30 p[find(x + n)] = find(y + n); 31 } 32 int ans1 = 0, ans2 = 0; 33 for (int i = 1;i <= n;i ++) 34 if (find(i) == find(1)) 35 ans1 ++; 36 for (int i = n + 1;i <= n + m;i ++) 37 if (find(i) == find(n + 1)) 38 ans2 ++; 39 cout << min(ans1, ans2) << endl; 40 return 0; 41 }
代码2 :
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define gogo ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL); 4 const string YES = "Yes"; 5 const string NO = "No"; 6 7 const int N = 30010; 8 int p[N]; 9 int n, m, s, q; 10 int find(int x) { 11 if (p[x] != x) p[x] = find(p[x]); 12 return p[x]; 13 } 14 int32_t main() { 15 gogo; 16 cin >> n >> m >> s >> q; 17 for (int i = 1;i <= n + m;i ++) 18 p[i] = i; 19 while (s --) { 20 int x, y; 21 cin >> x >> y; 22 if (find(x) != find(y)) 23 p[find(x)] = find(y); 24 } 25 while (q --) { 26 int x, y; 27 cin >> x >> y; 28 x = -x, y = -y; 29 if (find(x + n) != find(y + n)) 30 p[find(x + n)] = find(y + n); 31 } 32 int ans1 = 0, ans2 = 0; 33 for (int i = 1;i <= n;i ++) 34 if (find(i) == find(1)) 35 ans1 ++; 36 for (int i = n + 1;i <= n + m;i ++) 37 if (find(i) == find(n + 1)) 38 ans2 ++; 39 cout << min(ans1, ans2) << endl; 40 return 0; 41 }

浙公网安备 33010602011771号