poj1182 食物链(带权并查集)

题目告诉有  3  种动物,互相吃与被吃,现在告诉你  m  句话,其中有真有假,叫你判断假的个数  (  如果前面没有与当前话冲突的,即认为其为真话  )。每句话开始都有三个数 D A B,当D = 1时,表示A 和B是同类,当D = 2时表示A 吃 B。

题解参考:https://www.cnblogs.com/liuxin13/p/4668205.html

代码:

#include <iostream>
#include <cstdio>
#include <map>


using namespace std;

int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}

int n,m,t,a,b;
int f[100005],r[100005];

int find(int x){
    int k=f[x];
    if(f[x]!=x){
        f[x]=find(f[x]);
        r[x]=(r[k]+r[x])%3;
    }
    return f[x];
}

void unio(int a,int b){
    int fa=find(a);
    int fb=find(b);
    if(fa!=fb){
        f[fa]=fb;
    }
}

void init()
{
    for(int i=0;i<=n;i++)
    {
        f[i]=i;
        r[i]=0;
    }
}


int main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    n=read();m=read();
    init();
    int ans=0;
    while(m--){
        int x,y,d;
        d=read();x=read();y=read();
        int rx=find(x),ry=find(y);
        if(x>n||y>n||(d==2&&x==y)) ans++;
        else if(rx==ry&&(r[y]+d-1)%3!=r[x]) ans++;
        else if(rx!=ry){
            f[rx]=ry;
            r[rx]=((d-1)-r[x]+r[y]+3)%3;
        }

    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/Fy1999/p/9403460.html