并查集

并查集是一种用于处理一些不相交集合(Disjoint Sets)的合并及查询问题的树形数据结构,可以高效的解决多个元素的集合应用问题中:

合并集合、查询某元素属于某集合的问题

并查集的基本函数:

初始化:

1 void init()//未进行操作时没一个元素的祖先的是他自己
2 {
3     for (int i = 1; i <= n; i++)
4         f[i] = i;
5 }

查找:

1 int find(int x)//如果还没有查找到根节点(f[x]==x)
2 {               //就不断递归查找x的祖先的祖先(f[x]=find(find[x]))
3     return f[x] == x ? x : f[x] = find(f[x]);
4 }

合并:

1 void merge(int a, int b)
2 {
3     int x = find(a);
4     int y = find(y);
5     if (x != y)
6         f[y] = x;
7 }

基础并查集:

例题:洛谷 P1551 亲戚

 1 #include<iostream>
 2 using namespace std;
 3 const int maxn = 100010;
 4 int n, m, p, f[maxn];
 5 void init()
 6 {
 7     for (int i = 1; i <= n; i++)
 8         f[i] = i;
 9 }
10 int find(int x)
11 {
12     return f[x] == x ? x : find(f[x]);
13 }
14 void merge(int a, int b)
15 {
16     int x = find(a);
17     int y = find(b);
18     if (x != y)
19         f[y] = x;
20 }
21 int main()
22 {
23     cin >> n >> m >> p;
24     init();
25     for (int i = 1; i <= m; i++)
26     {
27         int a, b;
28         cin >> a >> b;
29         merge(a, b);
30     }
31     for (int i = 1; i <= p; i++)
32     {
33         int a, b;
34         cin >> a >> b;
35         if (find(a) == find(b))
36             cout << "Yes" << endl;
37         else
38             cout << "No" << endl;
39     }
40     return 0;
41 }

 拓展并查集:

例题:洛谷 P1525 关押罪犯

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 int n, m;
 6 struct people
 7 {
 8     int u, v, w;
 9 }p[100010];
10 int f[100010];
11 int e[100010];
12 bool cmp(people a, people b)
13 {
14     return a.w > b.w;
15 }
16 int find(int x)
17 {
18     return f[x] == x ? x : f[x] = find(f[x]);
19 }
20 void merge(int a, int b)
21 {
22     int x = find(a);
23     int y = find(b);
24     if (x != y)
25         f[y] = x;
26 }
27 int main()
28 {
29     cin >> n >> m;
30     for (int i = 1; i <= n; i++)
31         f[i] = i;
32     for (int i = 1; i <= m; i++)
33         cin >> p[i].u >> p[i].v >> p[i].w;
34     sort(p + 1, p + 1 + m, cmp);
35     for (int i = 1; i <= m; i++)
36     {
37         int a = p[i].u;
38         int b = p[i].v;
39         if (find(a) == find(b))
40         {
41             cout << p[i].w << endl;
42             return 0;
43         }
44         else
45         {
46             if (!e[a])
47             {
48                 e[a] = b;
49             }
50             else
51             {
52                 merge(e[a], b);
53             }
54             if (!e[b])
55             {
56                 e[b] = a;
57             }
58             else
59             {
60                 merge(e[b], a);
61             }
62         }
63     }
64     cout << 0 << endl;
65     return 0;
66 }

 特殊的并查集:

例题:P2024 [NOI2001]食物链

 1 #include<iostream>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdio>
 5 using namespace std;
 6 const int maxn = 100010;
 7 int n, m;
 8 int ans;
 9 int f[maxn * 3];
10 void init()
11 {
12     for (int i = 1; i <= n * 3; i++)
13         f[i] = i;
14 }
15 int find(int x)
16 {
17     return f[x] == x ? x : f[x] = find(f[x]);
18 }
19 void merge(int a, int b)
20 {
21     int x = find(a);
22     int y = find(b);
23     if (x != y)
24         f[y] = x;
25 }
26 int main()
27 {
28     cin >> n >> m;
29     init();
30     for(int i=1;i<=m;i++)
31     {
32         int t, x, y;
33         cin >> t >> x >> y;
34         if (x > n || y > n)
35         {
36             ans++;
37             continue;
38         }
39         if (t == 1)
40         {
41             if (find(x) == find(y + n) || find(x + n) == find(y))
42             {
43                 ans++;
44             }
45             else
46             {
47                 merge(x, y);
48                 merge(x + n, y + n);
49                 merge(x + 2 * n, y + 2 * n);
50             }
51         }
52         else
53         {
54             if (find(x) == find(y) || find(x) == find(y + n))
55             {
56                 ans++;
57             }
58             else
59             {
60                 merge(x + n, y);
61                 merge(x + 2 * n, y + n);
62                 merge(x, y + 2 * n);
63             }
64         }
65     }
66     cout << ans << endl;
67     return 0;
68 }
原文地址:https://www.cnblogs.com/HNFOX/p/11392270.html