并查集小结

并查集是一种竞赛中常用的数据结构,在解决划分集合问题,帮派问题,朋友关系问题方面有着很广的应用;

而对于并查集来说,基本的操作可以分为合并集合,查找集合,初始化集合等基本操作;

而对于并查集的应用背景,是这样的:一个城市有n个人,给出这些人的关系,比如1号,2号是朋友,2,3号也是朋友,那么1,3号就是朋友关系,在分析这些朋友的关系之后,我们就可以将这些是朋友的人划分为同一集合,最后统计有多少帮派

对于并查集的基本概念我觉得有必要总结一下:将1~n的不同对象划分为若干个不相交的集合,在每个集合中,选择某个元素代表所在的集合。

对于初始化我觉得有必要说一下:

我们初始化每个集合为以节点为元素的并查集,那么在开始的时候,每个集合都是独立的;

其余的有一篇讲的很好的博客,以喜闻乐见的火影来讲的,很有趣味性和可读性:

https://blog.csdn.net/weixin_38279101/article/details/112546053(转载)

实战项目:https://www.luogu.com.cn/problem/P1551

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int num=5010;
 4 int s[num];//集合 
 5 int height[num];//树的高度 
 6 int n,m,p;
 7 void init_set()//初始化集合 
 8 {
 9     for(register int i=1;i<=n;i++)
10     {
11         s[i]=i;
12         height[i]=0;
13     }
14 }
15 int find_set(int x)//查找函数 
16 {
17     if(x!=s[x])
18     s[x]=find_set(s[x]);
19     return s[x];
20 }
21 void union_set(int x,int y)//合并函数 
22 {
23     x=find_set(x);
24     y=find_set(y);
25     if(height[x]==height[y])
26     {
27         height[x]=height[x]+1;
28         s[y]=x;
29     }
30     if(height[x]<height[y])
31     {
32         s[x]=y;
33     }
34     else
35     s[y]=x;
36 }
37 int main()
38 {
39     std::ios::sync_with_stdio(false);
40     cin>>n>>m>>p;
41     init_set();
42     for(register int i=1;i<=m;i++)
43     {
44         int x,y;
45         cin>>x>>y;
46         union_set(x,y);
47     }
48     for(register int i=1;i<=p;i++)
49     {
50         int a,b;
51         cin>>a>>b;
52         if(find_set(a)==find_set(b))//如果是同一集合 
53         printf("Yes\n");
54         else
55         printf("No\n");
56     }
57     return 0;    
58 } 

https://www.luogu.com.cn/problem/P1536

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int s[1010];//集合 
 4 int height[1010];//树的高度 
 5 int ans;//统计 
 6 int n,m;
 7 void init_set()//合并 
 8 {
 9     for(register int i=1;i<=n;i++)
10     {
11         s[i]=i;
12         height[i]=0;
13     }
14 }
15 int find_set(int x)//查找 -路压 
16 {
17     if(x!=s[x])
18     {
19         s[x]=find_set(s[x]);
20     }
21     return s[x];
22 }
23 void union_set(int x,int y)//合并优化 
24 {
25     x=find_set(x);
26     y=find_set(y);
27     if(height[x]==height[y])
28     {
29         height[x]=height[x]+1;
30         s[y]=x;
31     }
32     if(height[x]<height[y])
33     {
34         s[x]=y;
35     }
36     else
37     {
38         s[y]=x;
39     }
40 }
41 int main()
42 {
43     std::ios::sync_with_stdio(false);
44     while(cin>>n>>m)
45     {
46         if(n==0)
47         return 0;
48         ans=0;
49         init_set();
50         for(register int i=1;i<=m;i++)
51         {
52             int x,y;
53             cin>>x>>y;
54             int a=find_set(x);
55             int b=find_set(y);
56             if(a!=b)
57             union_set(a,b);
58         }
59         for(register int j=1;j<=n;j++)
60         {
61             if(find_set(j)==j)
62             {
63                 ans++;
64             }
65         }
66         cout<<ans-1<<endl;
67     }
68     return 0;
69 } 

还有我的一篇博客:https://www.cnblogs.com/LQS-blog/p/16179533.html,

也是很经典的并查集问题

posted @ 2022-04-25 16:15  江上舟摇  阅读(18)  评论(0编辑  收藏  举报