题目链接
题意
给出n个虫子,m个关系,虫子只有两种性别,每条关系告诉你两只虫子是异性,请问是否有矛盾数据?
思路
裸的并查集,带权或者拓展都可以,我这里用的拓展并查集,感觉比带权好写得多
开两倍空间,1-n为虫子自己,n-2n为虫子的性转个体。同一集合内的虫子性别相同。那么对于每个关系u-v,如果发现uv的祖先节点一样,则出现了bug,否则的话,连接u和v+n,u+n和v。
初次写拓展并查集的话可以AC这道题后做一下食物链,我同样写了题解
代码
#include<iostream>
#include<cstdio>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
using namespace std;
typedef long long ll;
const int maxn=5000;
const int inf=0x3f3f3f3f;
int fa[maxn];
int tn,n,m;
void init(){
for(int i=0;i<maxn;i++)
fa[i]=i;
}
int find(int x){
return x==fa[x]?x:fa[x]=find(fa[x]);
}
void unite(int x,int y){
int fx=find(x),fy=find(y);
if(fx==fy)
return ;
fa[fx]=fy;
}
int main(){
scanf("%d",&tn);
for(int _=1;_<=tn;_++){
scanf("%d%d",&n,&m);
init();
bool bug=0;
while(m--){
int u,v;
scanf("%d%d",&u,&v);
if(bug)
continue;
int fu=find(u),fv=find(v);
if(fu==fv)
bug=1;
else
unite(u,v+n),unite(v,u+n);
}
if(bug)
printf("Scenario #%d:\nSuspicious bugs found!\n\n",_);
else
printf("Scenario #%d:\nNo suspicious bugs found!\n\n",_);
}
}