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>