种类并查集

Posted 7391_KID

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了种类并查集相关的知识,希望对你有一定的参考价值。

  一般的并查集是维护属于同一种类的元素,对于属于不同种类的元素之间的关系没有记录。种类并查集就是同一集合中的元素是已经确定关系的(是否属于同一种类),然后加一个group数组,记录一下孩子和父亲是否属于同一种类,递推稍稍改一下就可以了。

poj1703:http://poj.org/problem?id=1703

题目大意:有n个罪犯,两个帮派,已知其中若干对两者属于不同帮派,求给定的罪犯是否属于同一帮派。

需要注意,给的两个罪犯可能已经在同一个集合里了,需要处理一下,不然就无限递归了。。。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 const int maxn=1e5+5;
 6 int p[maxn],group[maxn],n,m;
 7 int Find(int x){
 8     if(p[x]==x)return x;
 9     int t=Find(p[x]);
10     group[x]=group[x]==group[p[x]]?1:0;
11     return p[x]=t;
12 }
13 void Unit(int a,int b){
14     int x=Find(a),y=Find(b);
15     if(x==y)return;
16     p[x]=b;
17     group[x]=1^group[a];
18 }
19 int Is_same(int a,int b){
20     int x=Find(a),y=Find(b);
21     if(x!=y)return -1;
22     return group[a]==group[b];
23 }
24 int main(){
25     int t,a,b;
26     char c;
27     scanf("%d",&t);
28     while(t--){
29         scanf("\\n%d%d",&n,&m);
30         for(int i=0;i<n;i++){p[i]=i;group[i]=1;}
31         for(int i=0;i<m;i++){
32             scanf("\\n%c%d%d",&c,&a,&b);
33             a--;b--;
34             if(c==\'D\'){
35                 Unit(a,b);
36             }else{
37                 int t=Is_same(a,b);
38                 if(t==-1)printf("Not sure yet.\\n");
39                 else if(t==0)printf("In different gangs.\\n");
40                 else if(t==1)printf("In the same gang.\\n");
41             }
42         }
43     }
44     return 0;
45 }

 

51nod 1204 Parity

分析:记前k个的和的奇偶性为f[k],若[a,b]和为偶数,则f[a]==f[b],否则f[a]!=f[b],然后用种类并查集维护一下就可以了。

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 const int maxn=100005;
 5 int p[maxn],group[maxn],n,q;
 6 int Find(int x){
 7     if(p[x]==x)return x;
 8     Find(p[x]);
 9     group[x]=group[p[x]]==group[x]?1:0;
10     p[x]=Find(p[x]);
11     return p[x];
12 }
13 int main(){
14     cin>>n>>q;
15     for(int i=0;i<=n;i++){p[i]=i;group[i]=1;}
16     int a,b,ans=-1;
17     char s[10];
18     for(int i=0;i<q;i++){
19         cin>>a>>b>>s;
20         int x=Find(a-1),y=Find(b);
21         if(s[0]==\'e\'){
22             if(x==y&&group[a-1]!=group[b]&&ans==-1)
23                 ans=i+1;
24             if(x!=y){
25                 p[x]=y;
26                 group[x]=group[a-1]==group[b]?1:0;
27             }
28         }else{
29             if(x==y&&group[a-1]==group[b]&&ans==-1)
30                 ans=i+1;
31             if(x!=y){
32                 p[x]=y;
33                 group[x]=group[a-1]==group[b]?0:1;
34             }
35         }
36     }
37     cout<<ans<<endl;
38     return 0;
39 }

 

以上是关于种类并查集的主要内容,如果未能解决你的问题,请参考以下文章

带权并查集(含种类并查集)经典模板 例题:①POJ 1182 食物链(经典)②HDU - 1829 A bug's life(简单) ③hihoCoder 1515 : 分数调查(示例代码(代

POJ 1733 Parity game(种类并查集)

种类并查集

BZOJ 4195: [Noi2015]程序自动分析 [并查集 离散化 | 种类并查集WA]

HDU1829(种类并查集)

poj 1182 食物链(种类并查集 ‘初心者’)