今天又重新复习了下并查集,发现食物链挺好的。
这次用的是枚举他们之间的关系,我觉得比赛时我也应该会这么写,而不是公式判断。
题意:
动物王国中有三类动物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),输出假话的总数。
// File Name: 1182.cpp // Author: Zlbing // Created Time: 2013年08月20日 星期二 13时32分43秒 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) const int MAXN=50000+100; int f[MAXN]; int r[MAXN]; int ans; int find(int x) { if(x==f[x])return x; int fa=find(f[x]); int t=f[x]; if(r[t]==1) { if(r[x]==0) r[x]=1; else if(r[x]==1) r[x]=2; else if (r[x]==2) { r[x]=0; } } else if(r[t]==2) { if(r[x]==0) r[x]=2; else if(r[x]==1) r[x]=0; else if(r[x]==2) { r[x]=1; } } f[x]=fa; return fa; } void unio(int x,int y,int kind) { int fx=find(x); int fy=find(y); if(fx!=fy) { f[fx]=fy; if(kind==1) { if(r[x]==0) { if(r[y]==0) { r[fx]=0; } else if(r[y]==1) { r[fx]=1; } else if(r[y]==2) { r[fx]=2; } } else if(r[x]==1) { if(r[y]==0) { r[fx]=2; } else if(r[y]==1) { r[fx]=0; } else if(r[y]==2) { r[fx]=1; } } else if(r[x]==2) { if(r[y]==0) { r[fx]=1; } else if(r[y]==1) { r[fx]=2; } else if(r[y]==2) { r[fx]=0; } } } else if(kind==2) { if(r[x]==0) { if(r[y]==0) { r[fx]=2; } else if(r[y]==1) { r[fx]=0; } else if(r[y]==2) { r[fx]=1; } } else if(r[x]==1) { if(r[y]==0) { r[fx]=1; } else if(r[y]==1) { r[fx]=2; } else if(r[y]==2) { r[fx]=0; } } else if(r[x]==2) { if(r[y]==0) { r[fx]=0; } else if(r[y]==1) { r[fx]=1; } else if(r[y]==2) { r[fx]=2; } } } } else { if(kind==1) { if(r[x]!=r[y]) ans++; } else if(kind==2) { if((r[x]+1)%3!=r[y]) ans++; } } } int main() { int n,m; scanf("%d%d",&n,&m); REP(i,1,n) { f[i]=i; r[i]=0; } ans=0; int a,b,c; REP(i,1,m) { scanf("%d%d%d",&a,&b,&c); if(b>n||c>n){ ans++; continue; } if(a==2&&b==c){ ans++; continue; } unio(b,c,a); //printf("i=%d ans=%d ",i,ans); } printf("%d ",ans); return 0; }