【经典种类并查集】食物链
食物链
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 53223 | Accepted: 15587 |
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),输出假话的总数。
现有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。
以下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
解法:
刚刚学了种类并查集,拿过来试试题,果然关于用并查集分类的话,无论是两类还是N多类都可以用种类并查集来实现的,主要还是要写好判断条件即可,同一个集合表示同一种类。
题目有三中分类,X,Y,Z,所以我们开一个区间为1~N,对于这个区间中的i,我们规定,i吃(i+N),(i+N)吃(i+2N),(i+2N)吃i。然后对输入的a和b进行判断,分类链接即可。
比如,输入1 a b的话,要先去判断(a和b+N),(a和b+2N)是否为同一类,如果为同一类的话,则说明a和b不可能为同一类了的。还有就是不能去直接判断(a和b)是否已经不是同一类的,因为你本来就还没连接,如果前面那条件都不符合的话,才去连接(a和b),(a+N和b+N),(a+2N和b+2N),他们为同一类,囧。。。。
对于输入2 a b的话,表示的是a吃b,所以,我们先去判断a和b是否为同一类,a和b+N是否同一类,如果是的话,则可以判断a吃b这关系是错误的。如果都不是,则说明(a+N和b),(a+2N和b+N),
(a和b+2N)为同一类,连接他们即可。
1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <math.h> 5 #define MAX 2000100 6 using namespace std; 7 int ID[MAX]; 8 void Cread(int N) 9 { 10 for(int i=1;i<=N;i++)ID[i]=i; 11 } 12 int Find(int x) 13 { 14 if(ID[x]!=x)ID[x]=Find(ID[x]); 15 return ID[x]; 16 } 17 void Add_(int a,int b) 18 { 19 int A=Find(a); 20 int B=Find(b); 21 if(A!=B)ID[A]=B; 22 } 23 int main() 24 { 25 int N,M,a,b,c,Sign,t=1; 26 scanf("%d%d",&N,&M); 27 { 28 Cread(3*N);Sign=0; 29 while(M--) 30 { 31 32 scanf("%d%d%d",&c,&b,&a); 33 if(a<=0||a>N||b<=0||b>N){Sign++;continue;} 34 if(c==1) 35 { 36 if(Find(a)==Find(b+N)||Find(a)==Find(b+2*N))Sign++; 37 else 38 { 39 Add_(a,b); 40 Add_(a+N,b+N); 41 Add_(a+2*N,b+2*N); 42 } 43 } 44 else 45 { 46 if(Find(a)==Find(b)||Find(a)==Find(b+N))Sign++; 47 else 48 { 49 Add_(a+N,b); 50 Add_(a,b+2*N); 51 Add_(a+2*N,b+N); 52 } 53 } 54 } 55 printf("%d\n",Sign); 56 } 57 return 0; 58 }
转载请备注:
**************************************
* 作者: Wurq
* 博客: https://www.cnblogs.com/Wurq/
* Gitee: https://gitee.com/wurq
**************************************
**************************************
* 作者: Wurq
* 博客: https://www.cnblogs.com/Wurq/
* Gitee: https://gitee.com/wurq
**************************************