poj2492 + 并查集

题目链接:http://poj.org/problem?id=2492

题目大意:每组测试数据给出n个虫子和m种交配组合,判断虫子中有没有同性交配的。

解决方案:首先大方向确定用并查集,每个虫子都初始化为一个集合。输入交配组合是,对每队虫子先判断他们是否在一个集合,如不在,则合并集合,若在,判断他们是否同性。判断方法为与祖先进行比较。

虽然思路很清楚,但要实现的好也不容易,花了一些时间去看别人的代码,然后才明白怎么实现才更好。

#include
#include
#define Max 2001
int parent[Max];
int relations[Max];     //与父亲的关系,0代表同性
void Init(int n)
{
    int i;
    for(i = 0;i <= n;i ++){
        parent[i] = i;
        relations[i] = 0;     
    }
    return;
}
int findSet(int x)
{
    int temp = parent[x];
    if(temp == x)
        return x;
    parent[x] = findSet(temp);
    relations[x] = (relations[x] + relations[temp]) % 2;  //由于之前可能已经发生了集合合并,祖先发生变动,所以要重新更新关系数组。对2取余后就可以代表与祖先的关系。
    return parent[x];
}

void unionSet(int a, int b)
{
    int root1 = findSet(a);
    int root2 = findSet(b);
    parent[root1] = root2;
    relations[root1] = (relations[a]-relations[b] + 1)%2;
}
int main(void)
{
    int i,t,n,m,a,b,flag,count;
    scanf("%d",&t);
    Init(Max - 1);
    count = 1;
    while(t --)
    {
        flag = 1;
        scanf("%d %d",&n,&m);
        for(i = 1;i <= m;i ++){
            scanf("%d %d",&a,&b);
            if(findSet(a) == findSet(b))
            {
                if(relations[a] != (relations[b] + 1) % 2)  //如果不满足异性关系,有矛盾
                    flag = 0;
            }
            else
            {
                unionSet(a, b);
            }
        }
        if(flag)
        {
            printf("Scenario #%d:\nNo suspicious bugs found!\n\n", count++);
        }
        else
        {
            printf("Scenario #%d:\nSuspicious bugs found!\n\n", count++);
        }
        Init(n);
    }
    return 0;
}

你可能感兴趣的:(并查集,ACM,poj)