poj 1182_食物链_并查集

lzusa 发布于 2019-04-28 900 次阅读


题目描述

动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。
现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。
有人用两种说法对这N个动物所构成的食物链关系进行描述:
第一种说法是“1 X Y”,表示X和Y是同类。
第二种说法是“2 X Y”,表示X吃Y。
此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
1) 当前的话与前面的某些真的话冲突,就是假话;
2) 当前的话中X或Y比N大,就是假话;
3) 当前的话表示X吃X,就是假话。
你的任务是根据给定的N(1<=N<=50,000)和K句话(0<=K<=100,000),输出假话的总数。

思路

用x表示A类,x+n表示B类,x+n*2表示C类,然后就可以在并查集中查找判断一下就可以了

#include 
int f[10000000];
int find(int x)
{
    if (!f[x]) return x;
    f[x]=find(f[x]);
    return f[x];
}
int insert(int x,int y)
{
    if (find(x)!=find(y))
    {
        f[find(x)]=find(y);
        return 1;
    }
    return 0;
}
int main()
{
    int n,m,ans=0;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if (y>n||z>n)
        {
            ans++;
            continue;
        }
        if (x==1)
        {
            if (find(y)==find(z+n)||find(y)==find(z+n*2)) ans++;
            else
            {
                insert(y,z);
                insert(y+n,z+n);
                insert(y+n*2,z+n*2);
            }
        }
        else if (x==2)
        {
            if (find(y)==find(z)||find(y)==find(z+n*2)) ans++;
            else
            {
                insert(y+n,z+n*2);
                insert(z,y+n*2);
                insert(z+n,y);
            }
        }
    }
    printf("%d\n",ans);
}
]]>