并查集之判断是否是二分图
(定义:设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。)
题意呵呵呵,男女各站一边,找出那对同性恋!
这里对每一对关系a和b,把自己的另一半和之前的另一半(如果有的话)合并,即他们是一个性别的。给出一对要判断的关系,如果两个点同时属于一边,则不是二分图,题目里面就是同性了。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#define ll __int64
using namespace std;
int r[2005],n,m,ans,pos[2005];
int root(int a)
{
if(r[a]==a) return a;
else return r[a]=root(r[a]);
}
void merge(int a,int b)
{
int ra,rb;
ra=root(a);
rb=root(b);
if(ra==rb) return;//不能在这把ans=0,这里的a和b是要合并的同性,而不是要判断的异性啊
else if(ra<rb)
r[rb]=ra;
else r[ra]=rb;
}
int main()
{
int cnt=0,a,b,t,i;
scanf("%d",&t);
while(t--)
{
cnt++;
scanf("%d%d",&n,&m);
ans=1;
memset(pos,0,sizeof pos);
for(i=0;i<=n;i++)
r[i]=i;
while(m--)
{
scanf("%d%d",&a,&b);
if(root(a)==root(b)) ans=0;
if(ans)
{
if(!pos[a]&&!pos[b])
{
pos[a]=b;
pos[b]=a;
}
else if(!pos[a])
{
pos[a]=b;
merge(a,pos[b]);
}
else if(!pos[b])
{
pos[b]=a;
merge(b,pos[a]);
}
else
{
merge(a,pos[b]);
merge(b,pos[a]);
}
}
}
printf("Scenario #%d:\n",cnt);
if(ans) printf("No suspicious bugs found!\n\n");
else printf("Suspicious bugs found!\n\n");
}
return 0;
}