题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1829
并查集高级运用:种类并查集,其关键在于结点与根结点的距离,如果距离是奇数那么性别就和根结点相反,如果是偶数就和根结点性别相同。
#include<cstdio>
#include<cstring>
const int MAX=1000005;
int bin[MAX];
int num[MAX];
int flag;
int find(int x)
{
if(x==bin[x])
return bin[x];
int r=find(bin[x]);
num[x]=(num[bin[x]]+num[x])&1; //找到该点的父节点,更新该点与父节点的关系
bin[x]=r;
return bin[x];
} //回溯之后即可得到祖先跟该节点的关系
void merge(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx==fy)
{
if(num[x]==num[y])
flag=true; 如果祖先相同,如果跟祖先的关系相同吗,这这两虫同性
return;
}
bin[fx]=fy;
num[fx]=(num[x]+num[y]+1)&1; 如果根不同,将x, <wbr>y建立关系,这里将y连接到x的根里面
}
int main()
{
int T,n,m;
scanf("%d",&T);
int t;
for(t=1;t<=T;t++)
{
scanf("%d%d",&m,&n);
flag=false;
int i,x,y;
for(i=0;i<=m;i++)
{
bin[i]=i;
num[i]=0;
}
for(i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
if(flag) continue;
merge(x,y);
}
printf("Scenario #%d:\n",t);
if(flag)
{
printf("Suspicious bugs found!\n");
}
else
{
printf("No suspicious bugs found!\n");
}
printf("\n") ;
}
return 0;
}