代码改变世界

暑假集训(2)第三弹 ----- 食物链(poj1182)

2016-07-22 20:10  HUAS_周林微  阅读(130)  评论(0编辑  收藏  举报
C - 食物链

Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%lld & %llu

Description

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

Input

第一行是两个整数N和K,以一个空格分隔。
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y。

Output

只有一个整数,表示假话的数目。

Sample Input

100 7
1 101 1 
2 1 2
2 2 3 
2 3 3 
1 1 3 
2 3 1 
1 5 5

Sample Output

3


问题分析:也是并查集,不过增加了三种属性,吃,同类,被吃,据其他人的解题报告,得知假设同类为0,吃为1,被吃为2,
其中有一个关系就是(父结点与爷爷结点的关系 + 儿子与父结点的关系)%3 = 儿子对爷爷的关系,通过它可以得到答案。
 1 #include "cstdio"
 2 
 3 int a[50001];
 4 int re[50001];
 5 int number;
 6 void abegin(int n)
 7 {
 8     for (int i=1;i<=n;i++)
 9        {
10             a[i] = i;
11             re[i] = 0;
12        }
13 }
14 int findroot(int x)
15 {
16     if(x != a[x])
17      {
18         int temp = a[x];
19         a[x] = findroot(temp);
20         re[x] = (re[x] + re[temp]) % 3;
21      }
22    return a[x];
23 }
24 void un(int b,int c,int d)
25 {
26    int x,y;
27    x = findroot(c);
28    y = findroot(d);
29    if (x == y)
30    {
31         if (b == 1 &&  re[c] != re[d])
32                  number++;
33         if (b == 2 && re[c] != (re[d] + 2) % 3)
34                  number++;
35    }
36    else
37    {
38         a[y] = x;
39         re[y] = (re[c] + b + 2 - re[d]) % 3;
40    }
41 }
42 int main()
43 {
44     int n,k;
45     int c,d,b;
46     scanf("%d%d",&n,&k);
47     number=0;
48     abegin(n);
49     while (k--)
50     {
51         scanf ("%d%d%d",&b,&c,&d);
52         if (c>n || d>n ||(b==2 && c==d))
53         {
54             number++;
55             continue;
56         }
57         un (b,c,d);
58     }
59     printf ("%d\n",number);
60     return 0;
61 }
View Code