POJ 1128 食物链

来源:互联网 发布:喵萝捏脸数据 百度云 编辑:程序博客网 时间:2024/06/10 08:11

0表示同类,1表示吃,2表示被吃。

这题的难点是推出合并两个集合后两个根节点的关系。

判断语句2是否为真话:为真的时候只有这三种情况:0,2 2,1 1,0.

#include <iostream>#include<stdio.h>#include<cmath>#include<stdlib.h>#include<cstring>using namespace std;int father[50005],v[50005]= {0};//v[ ]表示与父亲结点(查询后为与根结点)的关系int find(int x){    if(father[x]!=x)    {        int fa=father[x];        father[x]=find(father[x]);        v[x]=(v[fa]+v[x])%3;    }    else return x;    return father[x];}int link(int a,int b,int x,int y,int d){    father[b]=a;    v[b]=(v[x]-v[y]+3+d)%3;//注意合并后关系的变化,只用改变两个根结点的关系,之后的子结点会在查询根结点是更新}int main(){    int n,k,lie=0;    scanf("%d %d",&n,&k);    for(int i=1; i<=n; i++)    {        father[i]=i;    }    memset(v,0,sizeof(v));    while(k--)    {        int d,x,y,a,b;        scanf("%d %d %d",&d,&x,&y);        if(x>n||y>n)        {            lie++;            continue;        }        if(d==2&&x==y)        {            lie++;            continue;        }        a=find(x);        b=find(y);        if(d==1)        {            if(a!=b) link(a,b,x,y,0);            else if(v[x]!=v[y]) lie++;        }        if(d==2)        {            if(a!=b) link(a,b,x,y,1);            else  if(((v[x]+1)%3)!=v[y]) lie++;//注意这里不能写abs(v[x]-v[y])!=1因为有0 2的情况,之前没想到这个就一直WA        }   }    printf("%d\n",lie);    return 0;}