题目链接:http://poj.org/problem?id=1182
题意:三种关系,A吃B, B吃C,C吃A。给出k个句话,如果那句话和前面冲突即为假话
求假话出现的总数。
以前周赛考过一次,感觉好难,就溜了。(逃。。。
今天看《挑战...》看到有这道题目,感觉是时候来一发了。。。
因为有三种关系,扩增数组为3*N,每N个分别代表A 种类,B种类,C种类。
题目要求当D=1时,x和y为同类;D=2时,x吃y
//默认x为A物种,然后当D=1时,说明y不可能是B和C物种,也就是说他们的爸爸不可能一样
//当D=1时,说明x吃y,y不可以是A物种(因为捕食关系不可能同类),也不可以是C物种(C吃A)。
看了Gealo学长的博客,发现除了这种扩增法(扩增法因为数组的原因,数据一大很有可能爆内存,不是特别好)还有另外一种向量法,明天起来再补一发。
还有一件事,这个用cin,cout要时间超限。。。并且ios_base::sync_with_stdio(false);在里面完全没有效果。。。
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 const int N=50000; 6 int Father[3*N+1]; 7 8 void init(){ 9 for(int i=1;i<=3*N;i++) 10 Father[i]=i; 11 } 12 13 int find(int x){ 14 return x==Father[x] ? x : Father[x]=find(Father[x]); 15 } 16 17 void Union(int x,int y){ 18 int fx=find(x),fy=find(y); 19 if(fx!=fy){ 20 Father[fx]=fy; 21 } 22 } 23 24 int main(){ 25 int ans=0; 26 int n,k,t,x,y; 27 scanf("%d %d",&n,&k); 28 init(); 29 for(int i=0;i<k;i++){ 30 scanf("%d %d %d",&t,&x,&y); 31 if(x>n||x<1||y>n||y<1) {ans++;continue;} 32 if(t==1){ 33 if(find(x)==find(y+n)||find(x)==find(y+2*n)) ans++; 34 else{ 35 Union(x,y); 36 Union(x+n,y+n); 37 Union(x+2*n,y+2*n); 38 } 39 } 40 else{ 41 if(find(x)==find(y)||find(x)==find(y+2*n)) ans++; 42 else{ 43 Union(x,y+n); 44 Union(x+2*n,y); 45 Union(x+n,y+2*n); 46 } 47 } 48 } 49 50 printf("%d\n",ans); 51 return 0; 52 }
时间: 2024-10-26 06:07:31