POJ 2492 A Bug's Life(路径压缩并查集)
http://poj.org/problem?id=2492
题意:
有N个虫子和M次两个不同虫子的交流行为。虫子只有两种性别,且只有不同性别的虫子才会相互相互交流。问你这M次交流行为中是否有一些虫子违法了上述假设?
分析:
路径压缩并查集问题。
每个虫子对应并查集的一个节点,每个节点维护fa[i]:父节点编号,v[i]:i与父节点是否性别相同。如果v[i]==0,表示相同。如果v[i]==1,表示不相同。
如果两个虫子交互,那么合并他们的连通分量。如果有处于同一个连通分量且相同性别的两个虫子发生了交流,那么就存在了可疑的虫子。
AC代码:719ms
<span style="font-size:18px;">#include<cstdio> #include<cstring> using namespace std; const int MAXN=2000+100; int F[MAXN]; int v[MAXN]; int findset(int i) { if(F[i]==-1)return i; int temp=findset(F[i]); v[i] = (v[i]+v[F[i]])%2; return F[i]=temp; } void bind(int i,int j) { int fa=findset(i); int fb=findset(j); if(fa!=fb) { F[fb]=fa; v[fb]=(v[i]+v[j]+1)%2; } } int main() { int T,kase=1; int n,m; scanf("%d",&T); while(T--) { bool ok=true;//没有可疑的虫子被发现 memset(F,-1,sizeof(F)); memset(v,0,sizeof(v)); scanf("%d%d",&n,&m); while(m--) { int a,b; scanf("%d%d",&a,&b); int fa=findset(a); int fb=findset(b); if(fa!=fb) { bind(a,b);//这里切记是合并a和b 不是合并fa和fb } else if(fa==fb) { if(v[a]==v[b]) ok=false; } } if(ok==false) printf("Scenario #%d:\nSuspicious bugs found!\n\n",kase++); else if(ok==true) printf("Scenario #%d:\nNo suspicious bugs found!\n\n",kase++); } return 0; } </span>