Loading

扩展域并查集 || 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 }

 

posted @ 2023-02-09 20:16  KakaDBL  阅读(72)  评论(0)    收藏  举报