并查集模板

并查集模板题目: P3367

普通并查集模板:

初始化:

并查集数组每个元素初始自成一个集合,所以每个元素的值为其本身。所处的树的深度初始化为1

 

1 void init(int n)
2 {
3     for(int i = 1; i <= n; i++)
4     {
5         f[i] = i;
6         r[i] = 1;
7     }
8 }

 

代表元素的查找:

带有路径压缩的查找,递归写法:

 

1 int getfather(int x)
2 {
3     return f[x] == x?x:(f[x] = getfather(f[x]));
4 }

 

注意带括号,三元运算符优先级比等号高

两个集合的合并:

所处深度小的合并到深度大的

 

 1 void mergeset(int x, int y)
 2 {
 3     x = getfather(x); y = getfather(y); // 注意是父节点的合并
 4     if(getfather(x) != getfather(y))
 5     {
 6         if(r[x] <= r[y]) f[x] = y;
 7         else f[y] = x;
 8         if(r[x] == r[y] && x != y) r[x]++;
 9     }
10 }

 

整体代码(根据模板题写的):

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #define N 200010
 4 using namespace std;
 5 int f[N],r[N];
 6 void init(int n)
 7 {
 8     for(int i = 1; i <= n; i++)
 9     {
10         f[i] = i;
11         r[i] = 1;
12     }
13 }
14 int getfather(int x)
15 {
16     return f[x] == x?x:(f[x] = getfather(f[x]));
17 }
18 void mergeset(int x, int y)
19 {
20     x = getfather(x); y = getfather(y); 
21     if(getfather(x) != getfather(y))
22     {
23         if(r[x] <= r[y]) f[x] = y;
24         else f[y] = x;
25         if(r[x] == r[y] && x != y) r[x]++;
26     }
27 }
28 int main()
29 {
30     int n,m,z,x,y;
31     cin >> n >> m;
32     init(n);
33     while(m--)
34     {
35         cin >> z >> x >> y;
36         if(z == 1) mergeset(x,y);
37         else if(z == 2) cout << (getfather(x) == getfather(y)?'Y':'N') << endl;
38     }
39     return 0;
40 }
View Code

 

posted @ 2020-08-10 12:29  不敢说的梦  阅读(183)  评论(0)    收藏  举报