POJ2492——A Bug's Life(种类并查集)

传送门

大意:一个叫兽要研究一种虫子是否用同性恋的现象,给你几对恋爱的虫子

默认只有两种性别(???),问你是否存在同性恋的现象

----------------------------------------------------------------------------------------------(分割线)

如果忽视题意的话

是一道经典的带权并查集好题

考虑虫子只有两个种类

我们在合并并查集的时候再维护一个关系数组,表示这个点和根节点的关系(异性/同性)

这样我们可以知道同一个并查集内任意两点之间的关系

合并的时候两个并查集取反一下就是了

而如果出现两个相同的,就说明不满足条件

而关系只有0/1两种,用异或可以很方便的进行计算

话说输出记得打两个换行,我也不知道为什么要卡这个

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
inline int read(){
    char ch=getchar();
    int res=0;
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res;
}
int T,n,m,fa[2005],rel[2005];
inline int find(int x){
    int pre=fa[x];
    if(fa[x]!=x){
        fa[x]=find(fa[x]);
        rel[x]=(rel[x]^rel[pre]);
    }
    return fa[x];
}
int main(){
    T=read();
    for(int cas=1;cas<=T;cas++){
        memset(fa,0,sizeof(fa));memset(rel,0,sizeof(rel));
        n=read(),m=read();bool flag=false;
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++){
            int u=read(),v=read();
            int f1=find(u),f2=find(v);
            if(f1!=f2){
                fa[f1]=f2;rel[f1]=(rel[u]^rel[v]^1)%2;
            }
            else{
                if((rel[u]^rel[v])==0){
                    flag=true;
                }
            }
        }
        printf("Scenario #%d:
",cas);
        if(flag)printf("Suspicious bugs found!

");
        else printf("No suspicious bugs found!

");
    }
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366409.html