POJ 2492 A Bug is life

施法中………………………………………………………………….
……………………………………………………………………………
peng! 一道传送门:
http://poj.org/problem?id=2492

这题是类似于POJ1182食物链同样类型的,加权并查集。
可以先做这道题,之后在做1182—http://poj.org/problem?id=1182

先说说这道题,比较变态吧,研究虫子是不是同性恋。

我们在并查集的基础上加一个 r【】 代表当前点与其父节点的关系,我们假设0代表同性,1代表异性。

我们在找祖宗的时候我们可以想到每次更换父节点,r[]都会有所改变。

//我们用  int t代表当前点 x 的父节点。那么当我们更换父节点是,r[x]的值会改变。
//我们可以看到
x                 x的爹           xx他爹的爹(也就是x的爷爷)
0                   1                  1
1                   0                  1
1                   1                  1
0                   0                  0

这个大家最好自己 推倒 X我是污妖王X  一遍(当然你可以推倒好多次)

那么r[x]=(r[x]+r[t])%2

之后find_father的部分说完了,该联合的部分了

两个点联合,他们的关系应该怎么写呢?
我们假设  unite(int x,int y)   

xx为x的祖宗   yy为y的祖宗

当祖宗不同时,f[yy]=xx;sex[yy]=(sex[x]+sex[y]+1)%2;

这个公式是怎么推来的呢?

x对根节点 xx 为1    xx对x也为1     同理可得yy与y    之后+1
是因为  xy  结合   表明xy 恋爱   更改一下关系变好了,当然可以写成
sex[yy]= (sex[x]-sex[x]+1)%2   


好了附上代码:

#include <stdio.h>
#include <algorithm>
#include <string.h>
#define N 500100
using namespace std;
int f[N],sex[N];
int n,m;
void init(int n)
{
    for(int i=0;i<=n;i++)
    {
        f[i]=i;
        sex[i]=0;
    }
}
int find_father(int x)
{
    if(x==f[x])
        return x;
    int t=f[x];
    f[x]=find_father(f[x]);
    sex[x]=(sex[x]+sex[t])%2;
    return f[x];
}
void unin(int x,int y)
{
    int xx=find_father(x);
    int yy=find_father(y);
    if(xx!=yy)
    {
        f[yy]=xx;     // y-y father is---> xx;
        sex[yy]=(sex[y]+sex[x]+1)%2;    //  x 喜欢 y
    }
}
int main()
{
    int t,times=1,x,y;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        init(n);
        int flag=0;
        for(int i=0;i<m;i++)
        {
           scanf("%d %d",&x,&y);
           if(find_father(x)==find_father(y))
           {
               if(sex[x]!=(sex[y]+1)%2)
                 {
                     flag=1;
                 }
           }
           else
                unin(x,y);
       }

       printf("Scenario #%d:\n",times++);
       if(flag)
          printf("Suspicious bugs found!\n\n");
        else printf("No suspicious bugs found!\n\n");
    }
    return 0;
}

写的不好,请多指导。谢谢大家了。

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