poj1182食物链 并查集

    这题与hdu1829做法类似,在一棵树中,用0表示该节点与根节点相同,1表示该节点被根节点吃,-1表示该节点吃根节点。

#include<iostream>
#include<cstdio>

using namespace std;
const int maxn=50005;
int set[maxn],c[maxn];
//set记录父亲节点,c记录当前节点与根节点的关系
//0 :同类 1:被根节点吃 -1:吃根节点

void init(int n)
{
    for(int i=1;i<=n;i++)
    {
        set[i]=i;
        c[i]=0;
    }
}

inline int change(int x)
{
    if(x==2)
        return -1;
    else if(x==-2)
        return 1;
    else
        return x;
}

int find(int x)
{
    if(set[x]==x)
        return x;
    int t=set[x];
    set[x]=find(t);
    c[x]=change(c[x]+c[t]);//路径压缩并更新节点与根节点的关系
    return set[x];
}

bool merge(int x,int y,int d)
{
    int f1=find(x);
    int f2=find(y);
    if(f1==f2)
        return false;
    set[f1]=f2;
    c[f1]=change((c[y]-d-c[x]+1)%3);//画出食物链可以看出来
    return true;
}

int main()
{
    int n,m;
    int d,a,b,sum=0;
    scanf("%d%d",&n,&m);
    init(n);
    while(m--)
    {
        scanf("%d%d%d",&d,&a,&b);
        if(d==2&&a==b||a>n||b>n)
        {
            sum++;
            continue;
        }
        //若两种动物处于同一条食物链且不符合当前关系,则为假话
        if(!merge(a,b,d)&&change(c[b]-c[a])!=d-1)
            sum++;
    }
    printf("%d\n",sum);
    return 0;
}


 

你可能感兴趣的:(poj1182食物链 并查集)