食物链
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 Source |
本题的难点在于不是只有一类,而是有三类,找到一个维护这三个类的关系的方法就好做了。
1 #include <iostream> 2 #include <cstdio> 3 #define MAX_N 150000+5 4 5 using namespace std; 6 7 int par[MAX_N];//父节点 8 int depth[MAX_N];//深度 9 10 void init(int n){ 11 for(int i=0;i<=n;i++){ 12 par[i]=i; 13 depth[i]=1; 14 } 15 } 16 int find_father(int t){ 17 if(t==par[t]){ 18 return t; 19 }else{ 20 return par[t]=find_father(par[t]); 21 //实现了路径压缩 22 } 23 } 24 void unite(int t1,int t2){ 25 int f1=find_father(t1); 26 int f2=find_father(t2); 27 if(f1==f2){ 28 return ; 29 } 30 if(depth[f1]<depth[f2]){ 31 par[f1]=f2; 32 }else{ 33 par[f2]=f1; 34 if(depth[f1]==depth[f2]){ 35 depth[f1]++; 36 //记录深度 37 } 38 } 39 } 40 41 bool same(int x,int y){ 42 return find_father(x)==find_father(y); 43 } 44 45 int main() 46 { 47 int n,k; 48 int d,x,y; 49 int ans=0; 50 scanf("%d %d",&n,&k); 51 init(n*3); 52 for(int i=0;i<k;i++){ 53 scanf("%d %d %d",&d,&x,&y); 54 if(x<=0||x>n||y<=0||y>n||d==2&&x==y){ 55 ans++; 56 continue; 57 } 58 if(d==1){ 59 if(same(x,y+n)||same(x,y+2*n)){ 60 ans++; 61 continue; 62 }else{ 63 unite(x,y); 64 unite(x+n,y+n); 65 unite(x+2*n,y+2*n); 66 } 67 }else{ 68 if(same(x,y)||same(x,y+2*n)){ 69 ans++; 70 continue; 71 }else{ 72 unite(x,y+n); 73 unite(x+n,y+2*n); 74 unite(x+2*n,y); 75 } 76 } 77 } 78 printf("%d",ans); 79 return 0; 80 }
时间: 2024-10-13 16:46:17