食物链

描述

动物王国中有三类动物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),输出假话的总数。 

 
输入
第一行是两个整数N和K,以一个空格分隔。
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y。
输出
只有一个整数,表示假话的数目。
#include <cstdio>
#define MAXN 50005
struct node
{
 int parent;
 int relation; //表示和父结点的关系,0-同类,1-被吃,2-吃
} a[MAXN];
 int find(int x)
 {
     int s = x;
     int cur =0;
     int st[MAXN];
     while(a[s].parent > 0)
     {
         st[cur++] = a[s].relation;
         s = a[s].parent;
     }
     for(int i=cur-1; i>0; --i)
         st[i-1] = (st[i]+st[i-1])%3;
     cur = 0;
     while(s != x)
     {
         node tmp = a[x];
         a[x].parent = s;
         a[x].relation = st[cur++];
         x = tmp.parent;
     }
     return s;
 }
 void Union(int x,int y,int d)
 {
     int r1= find(x);
     int r2 = find(y);
     a[r2].parent = r1;
     a[r2].relation = (d+2+a[x].relation-a[y].relation)%3;
 }
 int main()
 {
 
     int n,k;
     scanf("%d%d",&n,&k);
     for(int i=1; i<=n; ++i)
     {
         a[i].parent = -1;
         a[i].relation = 0;
     }
     int num=0;
     while(k--)
     {
         int d,x,y;
         scanf("%d%d%d",&d,&x,&y);
         if(x > n || y>n || (d == 2 && x==y))
         {
             num++;
             continue;
         }
         int xp = find(x);
         int yp = find(y);
         if(xp != yp)
             Union(x,y,d);
         else
         {
             if(d == 1 && (a[x].relation+3-a[y].relation)%3 != 0)num++;
             if(d == 2 && (a[x].relation+3-a[y].relation)%3 != 2) num++;
         }
     }
     printf("%d\n",num);
     return 0;
 }

 

posted on 2013-04-27 15:42  耶稣爱你  阅读(394)  评论(0)    收藏  举报