P2024 [NOI2001]食物链(种类并查集)

题意:

现在有三种生物,ABC,A吃B,B吃C,C吃A,现在依次告诉你一些关系,请说出这些关系中假话的个数(假话的定义为与之前的话矛盾或不符合事实例如A吃A)

思路:

对于一对关系,比较难处理的是虽然你知道X吃Y,但是你不知道X跟Y究竟属于什么物种

那么我们可以建立3*N大小的并查集,分为A,B,C三个部分,代表着A中的生物吃B中的生物等等类推

对于一个关系比如X跟Y一类,我们在三个集合中分别将二者相连

对于关系X吃Y,我们就将A中的X与B中的Y相连,还有两个集合中操作类似

对于每个关系,我们就可以通过判断在一个集合内是否相连,或者在另一个集合内相连来判断正误了

#include
#include
#include
#include
 using namespace std;
 const int maxn=2e5+10;
 int fa[maxn];
 int find(int x){return fa[x]==x?x:(fa[x]=find(fa[x]));}
 int main()
 {
     int n,k,ans=0,op,x,y;
     scanf("%d%d",&n,&k);
     for(int i=1;i<=3*n;i++) fa[i]=i;
     for(int i=1;i<=k;i++){
         scanf("%d%d%d",&op,&x,&y);
         if(x>n||y>n){
             ans++;
             continue;
         }
        if(op==1){
            if(find(x)==find(y+n)||find(y)==find(x+n))    ans++;
            else{
                fa[find(x)]=find(y);
                fa[find(x+n)]=find(y+n);
                fa[find(x+2*n)]=find(y+2*n);
            }
        }
        else{
            if(x==y){ans++;continue;}
            if(find(x)==find(y)||find(x)==find(y+2*n)) ans++;
            else{
                fa[find(x)]=find(y+n);
                fa[find(x+n)]=find(y+2*n);
                fa[find(x+2*n)]=find(y);
            }
        }
     }
    cout<endl;
    return 0;
 }
 

 

你可能感兴趣的:(P2024 [NOI2001]食物链(种类并查集))