简单并查集 -- HDU 1232 UVALA 3644 HDU 1856

并查集模板:

 1 #include<iostream>
 2 using namespace std;
 3 int Rank[1001],x,y;
 4 int v[1001];
 5 //初始化 x 集合
 6 void init(int n)
 7 {
 8     for(int i=0; i<n; i++)
 9     {
10         v[i]=i;
11         Rank[i]=0;
12     }
13 }
14 //查找 x 所在的集合
15 int find_set(int x)
16 {
17     if(v[x]!=x) v[x]=find_set(v[x]);
18     return v[x];
19 }
20 ///更新根节点,有可能会暴栈
21 int mix(int x,int y)
22 {
23     int fx,fy;
24     fx=find_set(x);
25     fy=find_set(y);
26     if(fx!=fy)
27         p[fx]=fy;
28 }
29 //合并 x, y 所在的集合,用到路径压缩,按秩合并
30 void Union(int x,int y)
31 {
32     x=find_set(x);
33     y=find_set(y);
34     if(Rank[x]>Rank[y])
35         v[y]=x;
36     else if(Rank[x]<Rank[y])
37         v[x]=y;
38     else if(Rank[x]==Rank[y])
39     {
40         v[x]=y;
41         Rank[y]++;
42     }
43 }
44 int main()
45 {
46     return 0;
47 }
模板

计算环的个数,需要缩点:

 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <string>
 7 #include <sstream>
 8 #include <algorithm>
 9 #define maxn 100010
10 #define INF 0x7fffffff
11 #include <queue>
12 #define N 1000010
13 #define ll __int64
14 #define mem(a,b) memset(a,b,sizeof(a))
15 #define repu(i, a, b) for(int i = (a); i < (b); i++)
16 const double PI=-acos(-1.0);
17 using namesPce std;
18 ///初始化 x 集合
19 int P[maxn],Rank[maxn];
20 void mix()
21 {
22     repu(i,0,maxn)
23     {
24         P[i]=i;
25         Rank[i]=0;
26     }
27 }
28 ///查找 x 所在的集合
29 int find_set(int x)
30 {
31     if(P[x]!=x)
32         P[x]=find_set(P[x]);
33     return P[x];
34 }
35 ///缩点,合并 x, y 所在的集合,用到路径压缩,按秩合并
36 void Union(int x,int y)
37 {
38     x=find_set(x);
39     y=find_set(y);
40     if(Rank[x]>Rank[y])
41         P[y]=x;
42     else if(Rank[x]<Rank[y])
43         P[x]=y;
44     else if(Rank[x]==Rank[y])
45     {
46         P[x]=y;
47         Rank[y]++;
48     }
49 }
50 int main()
51 {
52     int x,y;
53     while(scanf("%d",&x) == 1)
54     {
55         mix();
56         int refu = 0;
57         while(x!=-1)
58         {
59             scanf("%d",&y);
60             x = find_set(x);
61             y = find_set(y);
62             if(x == y)///如果同一个根节点,就是环
63                 ++refu;
64             else
65                 Union(x,y);
66             scanf("%d",&x);
67         }
68         printf("%d
",refu);
69     }
70     return 0;
71 }
UVALA3644 find_set + Union

计算联通块的个数

题意:n个结点,m条边,求再连几条边能使得全部结点连通;

思路:并查集,求该图中有几个连通分支,然后连通块的个数-1;

 1 #include<iostream>
 2 #include<string>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<algorithm>
 7 #include<cmath>
 8 using namespace std;
 9 int p[50001];
10 int n,m;
11 int a,b;
12 int find_set(int x)
13 {
14     return p[x]==x?x:find_set(p[x]);
15 }
16 void mix(int x,int y)
17 {
18     int fx,fy;
19     fx=find_set(x);
20     fy=find_set(y);
21     if(fx!=fy)
22         p[fx]=fy;
23 }
24 int main()
25 {
26     int cas=1;
27     while(scanf("%d",&n)&&n)
28     {
29         scanf("%d",&m);
30         int count=0;
31         for(int i=1; i<=n; i++)
32             p[i]=i;
33         for(int j=1; j<=m; j++)
34         {
35             scanf("%d%d",&a,&b);
36             mix(a,b);
37         }
38         for(int i=1; i<=n; i++)
39             if(p[i]==i) count++;
40         printf("%d
",count-1);
41     }
42     return 0;
43 }
HDU 1232 find_set + mix

计算每个连通块个数,取最大:

 1 #include<cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <algorithm>
 5 using namespace std;
 6 struct A
 7 {
 8     int num,pre;
 9 } Set[10000011];
10 void init(int n)///初始化
11 {
12     int i;
13     for(i=1; i<=n; i++)
14     {
15         Set[i].num=1;
16         Set[i].pre=i;
17     }
18 }
19 int Find(int k)///找根节点
20 {
21     if(Set[k].pre==k)
22         return k;
23     return Set[k].pre = Find(Set[k].pre);
24 }
25 int main()
26 {
27     int n,maxn,ans,i,f1,f2;
28     int x[100011],y[100011];
29     while(~scanf("%d",&n))
30     {
31         if(n==0)
32         {
33             printf("1
");
34             continue;
35         }
36         maxn=0;
37         for(i=1; i<=n; i++)
38         {
39             scanf("%d%d",&x[i],&y[i]);
40             maxn = max(maxn,max(x[i],y[i]));
41         }
42         init(maxn);
43         for(i=1; i<=n; i++)
44         {
45             f1=Find(x[i]);
46             f2=Find(y[i]);
47             if(f1!=f2)
48             {
49                 Set[f1].pre=f2;
50                 Set[f2].num += Set[f1].num;///把该节点的子节点加上
51             }
52         }
53         ans=0;
54         for(i=1; i<=maxn; i++)
55             ans=max(ans,Set[i].num);
56         printf("%d
",ans);
57     }
58     return 0;
59 }
HDU 1856 find_set
原文地址:https://www.cnblogs.com/ACMERY/p/4526815.html