并查集-A Bug's Life(poj2492)

题意:
给出N条虫子,让a和b交配,
给出M对a和b交配后问,
有没有性别矛盾的虫子,
即和一只虫子和男的交配完之后又和女的交配
题解:
1.压缩路径关系转化,r[x] = (r[x]+r[f[x]])%2,很好理解//r[x]表示x和fx的关系,0同性,1异性
若x和fx为同性(r[x] = 0):
    fx和ffx为异性(r[fx] = 1),则x和ffx为异性,x和ffx的关系r[x]更新为0+1=1
    fx和ffx为同性(r[fx] = 0),则x和ffx为同性,x和ffx的关系r[x]更新为0+0=0
若x和fx为异性(r[x] = 1):
    fx和ffx为异性(r[fx] = 1),则x和ffx为同性,x和ffx的关系r[x]更新为(1+1)%2=0
    fx和ffx为同性(r[fx] = 0),则x和ffx为异性,x和ffx的关系r[x]更新为1+0=1
2.并查集联合若父节点相同
if(r[x] == r[y]) mark = true; //x和y性别不同,因为父节点相同,所以x,y和父节点关系相同就是假话
3.并查集联合若父节点不同,这句话为真话,把fy的父节点设置为fx
f[fy] = fx;
r[fy] = (1+r[x]-r[y])%2;

   

 #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int f[2010], r[2010];//f数组指向与它交配的bug,初始化自交
    //r表示他的父节点与它是同性还是异性,0同性,1异性
    bool mark;
    int find_head(int x)
    {
        int fx = x;
        if(x != f[x])
        {
            fx = find_head(f[x]);
            r[x] = (r[x]+r[f[x]])%2;
            f[x] = fx;
        }
        return fx;
    }
    void union_set(int x, int y)
    {
        int fx = find_head(x);
        int fy = find_head(y);
        if(fx == fy)//父亲结点相同
        {
            if(r[x] == r[y]) //x和y性别不同,因为父节点相同,所以x,y和父节点关系相同就是假话
            {
                mark = true;
            }
        }
        else//父亲结点不同,这句话为真话,把fy的父节点设置为fx
        {
            f[fy] = fx;
            r[fy] = (1+r[x]-r[y])%2;
        }
    }
    int main()
    {
        int t;
        cin>>t;
        for(int i = 1; i <= t; i++)
        {
            int n, m;
            mark = false;
            scanf("%d%d", &n,&m);
            memset(r, 0, sizeof(r));
            for(int k = 1; k <= 2010; k++)
            {
                f[k] = k;
            }
            for(int j = 1; j <= m; j++)
            {
                int x, y;
                scanf("%d%d", &x,&y);
                if(!mark)
                {
                    union_set(x, y);
                }
            }
            cout<<"Scenario #"<<i<<":"<<endl;
            if(mark) cout<<"Suspicious bugs found!"<<endl;
            else cout<<"No suspicious bugs found!"<<endl;
            cout<<endl;
        }
    }

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值