POJ 1182_食物链

来源:互联网 发布:海康提示网络不可达 编辑:程序博客网 时间:2024/06/02 04:15

题意:

三种动物A,B,C,A吃B,B吃C,C吃A,
有人用两种说法对这N个动物所构成的食物链关系进行描述:
第一种说法是”1 X Y”,表示X和Y是同类。
第二种说法是”2 X Y”,表示X吃Y。
此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
1) 当前的话与前面的某些真的话冲突,就是假话;
2) 当前的话中X或Y比N大,就是假话;
3) 当前的话表示X吃X,就是假话。
求假话数

分析:

最初想到用三个并查集分别表示A,B,C,然后用数组表示之间的联系,可是操作起来很麻烦,过了样例也一直WA,后来看了《挑战程序设计竞赛》上的解法,用偏移量表示他们之间的关系,处理起来方便很多。即
X为A,X+N为B,X+2*N为C

代码:

#include<iostream>#include<cstdio>using namespace std;const int maxn = 500055;int pa[maxn], _rank[maxn];int _find(int x){    if(pa[x]==x) return x;    else return pa[x]=_find(pa[x]);}void unite(int x, int y){    int rx = _find(x), ry = _find(y);    if(rx==ry) return;    if(_rank[rx]>_rank[ry]) pa[ry]=rx;    else {        pa[rx] = ry;        if(_rank[rx]==_rank[ry]) _rank[ry]++;    }    return;}bool same(int x, int y){    return _find(x)==_find(y);}int main (void){    int n, k ;scanf("%d%d",&n,&k);    for(int i = 1; i <= 3 * n; i++) pa[i] = i;    int x, y, f, cnt = 0;    int mod = 3 * n;    for(int i = 0; i < k; i++){        scanf("%d%d%d",&f,&x,&y);        if(x>n||y>n) {cnt++;continue;}        if(f==1){            if(same(x,y+n)||same(x,y+2*n)) cnt++;            else{                unite(x,y);                unite(x+n,y+n);                unite(x+2*n,y+2*n);            }        }else {            if(same(x,y)||same(x, y + 2*n)) cnt++;            else {                unite(x, y+n);                unite(x+n,y+2*n);                unite(x+2*n, y);            }        }    }    printf("%d\n",cnt);}
0 0
原创粉丝点击