食物链

题目描述

        动物王国中有三类动物  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。

输出

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

样例输入

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

样例输出

3

提示

100 7
1 101 1    假话 
2 1 2      真话 
2 2 3      真话 
2 3 3      假话 
1 1 3      假话 
2 3 1      真话 
1 5 5      真话 
 
【胡乱分析】
用1~n表示动物,n+1~2n表示吃某动物的动物,2n+1到3n表示被吃的动物;如:a+n表示吃a的,a+2n表示吃b的;所以一开始在存fa[]和size[]的时候也是1~3n。余下的看代码。这次主要的问题是语文,把三类动物和n个动物弄混了。
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 using namespace std;
 7 const int M = 200000;
 8 int fa[M],size[M];
 9 int find(int x)
10 {
11     if(fa[x] != x) return fa[x] = find(fa[x]);
12     return fa[x];
13 }
14 void unionn(int x,int y)
15 {
16     x = find(x);
17     y = find(y);
18     if(x == y) return;//如果两个已经在同一个集合中了,就不用操作 
19     else
20     {
21         if(size[x] > size[y])//小的往大的里合并 
22         {
23             size[x] += size[y];
24             fa[y] = x; 
25         }
26         else
27         {
28             size[y] += size[x];
29             fa[x] = y;
30         }
31     }
32 }
33 int main()
34 {
35     int n,k,d,a,b,ans = 0;
36     scanf("%d%d",&n,&k);
37     for(int i = 1;i <= 3 * n;i++)
38     {
39         fa[i] = i;
40         size[i] = 1;
41     }
42     for(int i = 1;i <= k;i++)
43     {
44         scanf("%d%d%d",&d,&a,&b);
45         if(a > n || b > n)//如果动物编号大于动物个数,则是假话 
46         {
47             ans++;
48         }
49         else
50         {
51             if(d == 1)
52             {
53                 if(find(a) == find(b + n) || find(a) == find(b + 2 * n)) ans++;//如果a和吃b的动物为一类,则a不可能跟b是同类;如果a和被b吃的是同类,他俩也不可能为同类 
54                 else//如果这句话是真的 
55                 {
56                     unionn(a,b);//合并a,b为一类 
57                     unionn(a + n,b + n);//吃a的动物也吃b 
58                     unionn(a + 2 * n,b + 2 * n);//被a吃的动物也被b吃 
59                 }
60             }
61             else
62             {
63                 if(find(a) == find(b) || find(a) == find(b + 2 * n)) ans++;//如果ab为一类或a与被b吃的是一类,则a不可能吃b 
64                 else
65                 {
66                     unionn(a,b + n);//a和吃b 的是一类 
67                     unionn(a + 2 * n,b);//被a吃的和b 是一类 
68                     unionn(a + n,b + 2 * n);//由于一共有三类动物,所以吃a的和被b吃的是一类。 
69                 }
70             }
71         }
72     }
73     printf("%d",ans);
74     return 0;
75 }
原文地址:https://www.cnblogs.com/peppa/p/9025247.html