博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

并查集

Posted on 2019-10-22 11:54  淼哥学习园地  阅读(270)  评论(0)    收藏  举报

例题一:合并集合:

 

 

 1 #include<iostream>
 2 
 3 using namespace std;
 4 
 5 const int N=100010;
 6 
 7 int a[N],p[N];
 8 int n,m;
 9 
10 int find(int x)
11 {
12     if(p[x]!=x) p[x]=find(p[x]);
13     
14     return p[x];
15 }
16 f
17 int main()
18 {
19     cin>>n>>m;
20     for(int i=1;i<=n;i++)
21     {
22         scanf("%d",&a[i]);
23         p[i]=i;
24     }
25     while(m--)
26     {
27         char op;
28         cin>>op;
29         if(op=='M')
30         {
31             int x,y;
32             cin>>x>>y;
33             if(find(x)!=find(y)) p[find(x)]=find(y);
34             
35         }
36         else
37         {
38             int x,y;
39             cin>>x>>y;
40             if(find(x)==find(y))
41                 puts("Yes");
42             else
43                 puts("No");
44         }
45     }
46     
47     return 0;
48 }

 

 

 

例题二:用并查集维护信息

 

 

只要我们知道每个点和根节点的关系,就知道任意俩个点之间的关系。

可以用每个点到根节点的距离来表示关系: 1 (吃根节点) 2(吃1  被根节点吃) 3 (同类) mod 3  余1(吃根节点,吃余0) 余2(被根节点吃,吃余1)  余0(和根节点同类,吃余2)

 

 

 

距离的含义: x吃y (y到x的距离为1)

 我们只能记录每一个点到根节点的距离(每次求完一次并查集都会做路劲压缩,将到父节点的距离改成到根节点的距离)

 

这就好比公司里每个人的等级:要判断每个人直接的等级,只需要记录每个人与领袖之间的等级就可以知道各个人直接的关系。

 

 1 #include <iostream>
 2 
 3 using namespace std;
 4 const int N=500010;
 5 int p[N],d[N];
 6 int n,m;
 7 
 8 
 9 //并查集
10 int find(int x)
11 {
12     if(p[x]!=x)
13     {
14         int t=find(p[x]);
15         d[x]+=d[p[x]];
16         p[x]=t;
17     }
18     return p[x];
19 }
20 
21 
22 
23 int main()
24 {
25     cin>>n>>m;
26     
27     for(int i=1;i<=n;i++) p[i]=i;
28     
29     int res=0;
30     
31     while(m--){
32         int t,x,y;
33         cin>>t>>x>>y;
34         
35         if(x>n || y>n)
36         {
37             res++;
38         }
39         else{
40             int px=find(x),py=find(y);  //px==x的根节点 py==y的根节点
41             if(t==1)
42             {
43                 if(px==py && (d[x]-d[y])%3) res++;   //如果在同一颗树上且mod3余数不为0
44                 else if(px!=py)            //不在同一棵树上
45                 {
46                     p[px]=py;           //将x连到y树上
47                     d[px]=d[y]-d[x];    
48                 }
49                 
50             }
51             else{
52                 if(px==py && (d[x]-d[y]-1)%3) res++;     //xy在同一颗树上,且x-y%3==1 不成立
53                 else if(px!=py)
54                 {
55                     p[px]=py;
56                     d[px]=d[y]+1-d[x];    //(d[x]+?-d[y])%3==1   
57                 }
58             }
59         }
60         
61     }
62     
63     cout<<res<<endl;
64     
65     return 0;
66     
67     
68 }