并查集

幷查集是一種很diao的數據結構,應用的很典型的栗子就是找共同的祖先,或者說是一組數字指向同一個根,是一種樹形的結構;

具體可以看一下這裡:別人家的博客

比如,給出幾個數,作為同學的編號,他們的初始父親是一個叫-1的節點:

-1 -1  -1  -1

1 2 3 4

如果他們有著同樣的興趣愛好,那麼就可以把它們合併到同一個父親節點上,比如合併到1:

1 1 1 1

1 2 3 4

這樣就形成了一個樹形的結構

  1

2 3 4

本來1234是四個人的,現在變成了同一個興趣小組,所以幷查集可以看作是一個合併的過程,下面看他的具體應用:

只要理解上面的就沒有問題!

poj 2524. Ubiquitous Religions

 1 // poj 2524. Ubiquitous Religions
 2 // 并查集 求最多有多少个祖先
 3 // references:
 4 // no
 5 #include <iostream>
 6 #include <cstdio>
 7 #include <cstring>
 8 #include <algorithm>
 9 
10 using namespace std;
11 
12 int p[50005];
13 int ans;
14 
15 void init()
16 {
17     memset(p, -1, sizeof(p));
18 }
19 
20 int find(int x)
21 {
22     return p[x] == -1 ? x : p[x] = find(p[x]);
23 }
24 
25 void union_set(int u, int v)
26 {
27     int x = find(u);
28     int y = find(v);
29     if(x != y)
30     {
31         p[x] = y;
32         ans--;
33     }
34 }
35 
36 int main()
37 {
38     int n, m, k = 1;
39     while(scanf("%d%d", &n, &m) != EOF, n, m)
40     {
41         ans = n;
42         init();
43         int u, v;
44         for(int i=0; i<m; i++)
45         {
46             scanf("%d%d", &u, &v);
47             union_set(u, v);
48         }
49         printf("Case %d: %d
", k++, ans);
50     }
51     return 0;
52 }

poj 1611.The Suspects

 1 // poj 1611.The Suspects
 2 // 并查集
 3 // references:
 4 // no
 5 #include <iostream>
 6 #include <cstdio>
 7 #include <cstring>
 8 #include <algorithm>
 9 
10 using namespace std;
11 
12 const int N = 30005;
13 int n, m;
14 int p[N];
15 int num[N];
16 
17 void init()
18 {
19     for(int i=0; i<n; i++)
20     {
21         p[i] = -1;
22         num[i] = 1;        //记录该点为祖先的后代个数 
23     }
24 }
25 
26 int find(int x)
27 {
28     return p[x] == -1 ? x : p[x] = find(p[x]);
29 }
30 
31 void union_set(int u, int v)
32 {
33     int x = find(u);
34     int y = find(v);
35     if(x != y)
36     {
37         p[x] = y;
38         num[y] += num[x];    //注意这里是加上x的num[],不只是++;    
39     }    
40 }
41 
42 int main()
43 {
44     while(scanf("%d%d", &n, &m) != EOF, n)
45     {
46         init();
47         for(int i=0; i<m; i++)
48         {
49             int k, u, v;
50             scanf("%d", &k);
51             scanf("%d", &u);
52             for(int j=1; j<k; j++)
53             {
54                 scanf("%d", &v);
55                 union_set(u, v);    //都跟第一个合并 
56                 //u = v;
57             }
58         }
59         int x = find(0);    //找到0的祖先 
60         printf("%d
", num[x]);
61     }
62     return 0;
63 }
原文地址:https://www.cnblogs.com/dominjune/p/4720262.html