并查集---体会以及模板&&How Many Tables - HDU 1213

定义&&概念:

啥是并查集,就是将所有有相关性的元素放在一个集合里面,整体形成一个树型结构,它支持合并操作,但却不支持删除操作

实现步骤:
(1)初始化,将所有节点的父亲节点都设置为自己,例如pre[1]=1
(2)合并,将一个元素或者一集合(两者间有联系)合并到另外一个集合(元素)里面,谁是谁的父亲节点不需要过多在意,视题意而定。
(3)查找,在合并时需要运用到查找操作,即查找该元素的父节点,尽量使用路径压缩,可以使并查集更加高效,一旦使用了路径压缩,查询时就会将该查询元素到父亲的边改为直接连向根。

这道模板题方便理解:

并查集模板题How Many Tables - HDU 1213 - Virtual Judge

题意:

今天是Ignatius的生日,他邀请了许多朋友。现在是吃晚饭的时间,Ignatius想知道他至少需要准备多少桌。

必须注意的是,并非所有的朋友都相互认识对方,有的人不愿意和陌生人坐在一桌。

针对此问题的一个重要的规则是,如果我告诉你A知道B,B知道C,这意味着,A和C认识对方,这样他们就可以留在一个桌子。但是如果我告诉你,A知道B,B知道C,D知道E,那么ABC可以坐在一起,DE就得另外再坐一桌了。你的任务是请根据输入的朋友之间的关系,帮助Ignatius 求出需要安排多少桌。

input:

2
5 3
1 2
2 3
4 5

5 1
2 5

output:

2
4

思路:有几张桌子就是有几个集合,最后查找一下有几个祖宗节点就是答案啦

扫描二维码关注公众号,回复: 9068189 查看本文章

ps:并查集的核心就是同一个集合内各个元素都是有关系的

在查询祖宗节点的时候尽量用路径压缩稍微优化一下,可以提高查询效率

 1 #include<iostream>
 2 #include <algorithm>
 3 #include <queue>
 4 #include<cstring>
 5 #include<stdio.h>
 6 using namespace std;
 7 //有几个集合就有几张桌子 
 8 int n,m;
 9 int father[30005],vis[30005];
10 struct node{
11     int father;
12     
13 }star[30005];
14 int Find(int x){//查询 
15     //return x==father[x]? x : Find(father[x]);
16     
17     //路径压缩,直接与祖宗节点相连,加快查询速度 
18     if(x!=star[x].father){
19         star[x].father=Find(star[x].father); 
20     }
21     return star[x].father;
22 }
23 void combine(int a,int b){//合并 
24     //找到各自的祖宗 
25     int fa=Find(a);
26     int fb=Find(b);
27     if(fa==fb)return;
28     else{//合并组织 
29         star[fb].father=fa;
30     } 
31 }
32 
33 int main() 
34 {    
35     ios::sync_with_stdio(false);
36     cin.tie(0);
37     int t;
38     //~scanf("%d%d",&n,&m)
39     cin>>t;
40     while(t--){
41         memset(vis,0,sizeof(vis));
42         cin>>n>>m;
43         
44         int a,b;
45         for(int i=1;i<=n;i++){
46             star[i].father=i;
47         }
48         for(int i=1;i<=m;i++){
49             cin>>a>>b;
50             combine(a,b);
51         }
52         int ans=0;
53         for(int i=1;i<=n;i++){
54             int pos=Find(i);
55             
56             if(!vis[pos]){
57                 ans++;vis[pos]=1;
58             }
59         }
60         cout<<ans<<endl;
61     } 
62     
63     
64     return 0;
65 }

猜你喜欢

转载自www.cnblogs.com/simaomao/p/12292848.html