NOI2001食物链

描述

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

输出格式

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

样例1

样例输入1[复制]

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

样例输出1[复制]

 
3

限制

1S

提示

并查集
对样例的解释
输入文件 对7句话的分析
100 7
1 101 1 假话
2 1 2 真话
2 2 3 真话
2 3 3 假话
1 1 3 假话
2 3 1 真话
1 5 5 真话 

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<vector>
 7 #include<map>
 8 #include<set>
 9 #include<stack>
10 #include<string>
11 #include<algorithm>
12 #define maxn 150000+50
13 #define inf 0x7fffffff
14 #define  xiao 1e-9
15 using namespace std;
16 int fa[maxn],p[maxn],n,m; 
17 void prepared()//初始化 
18 {
19     for(int i=1;i<=n*3;++i) p[i]=i;
20     for(int i=1;i<=n;++i)
21     {
22         fa[i]=i+n;
23         fa[i+n]=i+2*n;
24         fa[i+2*n]=i;
25     }
26 }
27 int find(int x)//每个动物群的代表元素 
28 {
29     if(p[x]!=x) p[x]=find(p[x]);
30     return p[x];
31 }
32 void work()
33 {
34     int ans=0;
35     int q,x,y;
36     scanf("%d",&m);
37     for(int i=1;i<=m;++i)
38     {
39         scanf("%d%d%d",&q,&x,&y);
40         if(x>n||y>n) {ans++;continue;}
41         int a[3],b[3];//a,b为两种动物维护的三个域 
42         a[0]=find(x),b[0]=find(y);//代表元素 
43         a[1]=fa[a[0]],a[2]=fa[a[1]];//a[1]为这种动物的被吃域,a[2]为吃域 
44         b[1]=fa[b[0]],b[2]=fa[b[1]];//同上 
45         bool flag=false;
46         for(int i=0;i<3;++i)
47         {
48             if(a[0]==b[i]) {flag=true;break;}//是否在一个环内 
49         }
50         if(q==1)
51         {
52             if(flag) 
53             {
54                 if(a[0]!=b[0]) ans++;//如果代表元素不同说明不是一类,此话为假 
55             }
56             else
57             {
58                 for(int i=0;i<3;++i) p[b[i]]=a[i];//合并操作 
59             }
60         }
61         else
62         {
63             if(x==y) {ans++;continue;}
64             if(flag==true) 
65             {
66                 if(fa[b[0]]!=a[0])     ans++;//如果b的被吃对象不是 a,此话为假 
67             }
68             else 
69             {for(int i=0;i<3;++i) p[b[i]]=a[(i+2)%3];}//等价于{p[b[0]]=a[2];p[b[1]]=a[0];p[b[2]]=a[1];}
70         }
71     }
72     cout<<ans;
73 }
74 int main()
75 {
76     scanf("%d",&n);
77     prepared();
78     work();
79     return 0;
80 }

 

posted @ 2015-11-05 20:00  Maydaytyh  阅读(258)  评论(0编辑  收藏  举报