POJ 2492 A Bug's Life(路径压缩并查集)

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>


你可能感兴趣的:(ACM)