食物链
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 113794 | Accepted: 34597 |
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
Source
1 #include <cstdio> 2 #include <iostream> 3 4 5 using namespace std; 6 7 const int max_N=50000+2; 8 const int max_K=1e5+2; 9 int N,K; 10 int T[max_K],X[max_K],Y[max_K]; 11 12 // 并查集的实现 13 // 三个并查集 14 int par[max_N*3]; 15 int ranks[max_N*3]; 16 17 void init(int n) 18 { 19 for(int i=0;i<n;++i) 20 { 21 par[i]=i; 22 ranks[i]=0; 23 } 24 } 25 26 // 寻找所属的类的编号,并优化路径上的所有点 27 int finds(int x) 28 { 29 if(par[x]==x) 30 { 31 return x; 32 } 33 else 34 { 35 // 路径压缩 36 return par[x]=finds(par[x]); 37 } 38 } 39 40 // 并查集合并操作 41 void unite(int x,int y) 42 { 43 x=finds(x); 44 y=finds(y); 45 46 if(x==y) 47 { 48 return; 49 } 50 51 // 合并到深度大的那颗树 52 if(ranks[x]<ranks[y]) 53 { 54 par[x]=y; 55 } 56 else if(ranks[x]==ranks[y]) 57 { 58 // 随意连边,这边向y连边 59 par[x]=y; 60 ++ ranks[y]; 61 //par[y]=x;++ranks[x]; 62 } 63 else 64 { 65 par[y]=x; 66 } 67 } 68 69 bool same(int x,int y) 70 { 71 return finds(x)==finds(y); 72 } 73 74 void solve() 75 { 76 // 错误信息数 77 int ans=0; 78 // 初始化并查集 79 init(N*3); 80 81 for(int i=0;i<K;++i) 82 { 83 int x=X[i]-1; 84 int y=Y[i]-1; 85 86 if(x<0 || x>=N || y<0 || y>=N) 87 { 88 ++ans; 89 continue; 90 } 91 92 // X 与 Y 是同一类 93 if(T[i]==1) 94 { 95 96 // 冲突的情况 97 // 1. x吃y 98 // 2. y吃x 99 if(same(x,y+N) || same(y+2*N,x)) 100 { 101 ++ans; 102 } 103 else 104 { 105 unite(x,y); 106 unite(x+N,y+N); 107 unite(x+2*N,y+2*N); 108 } 109 } 110 // X 吃 Y 111 else 112 { 113 114 // 冲突的情况 115 // 1. x与y同一类 116 // 2. y吃x 117 if(same(x,y) || same(y+2*N,x)) 118 { 119 ++ans; 120 } 121 else 122 { 123 unite(x,y+N); 124 unite(x+N,y+2*N); 125 unite(x+2*N,y); 126 } 127 } 128 } 129 130 131 printf("%d ",ans); 132 } 133 134 int main() 135 { 136 scanf("%d %d",&N,&K); 137 for(int i=0;i<K;++i) 138 { 139 scanf("%d %d %d",&T[i],&X[i],&Y[i]); 140 } 141 142 solve(); 143 144 return 0; 145 } 146 147 148 /* 149 150 100 7 151 1 101 1 152 2 1 2 153 2 2 3 154 2 3 3 155 1 1 3 156 2 3 1 157 1 5 5 158 */