题目大意:给出N条虫子,然后a和b啪啪啪,给出M对a和b啪啪啪的关系,然后问有没有同性恋的虫子~~
解题思路:并查集,按秩合并,rank[i]表示i和他的父亲节点是不是同性,在查找和合并的时候秩需要改变,改变方式具体看代码,这个杭电里我做过的一道题有点像.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=5000+100;
int p[maxn],Rank[maxn],n,m;
void init()
{
for(int i=1; i<=n; i++)
{
p[i]=i;
Rank[i]=1;
}
}
int Find_Set(int u)
{
if(p[u]==u) return u;
else
{
int tmp=p[u];
p[u]=Find_Set(p[u]);
Rank[u]=(Rank[u]+Rank[tmp]+1)%2;//改变他的秩
return p[u];
}
}
int combine_set(int x,int y)
{
int a=Find_Set(x);
int b=Find_Set(y);
if(a==b) return 1;
else
{
p[b]=a;
Rank[b]=(Rank[x]+Rank[y])%2;
return 0;
}
}
int main()
{
int kase=1,T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
int u,v;
int flag=0;
for(int i=1; i<=m; i++)
{
scanf("%d%d",&u,&v);
if(flag==0)//找到就不比较了,节省效率
{
if( Find_Set(u)==Find_Set(v))
{
if((Rank[u]+Rank[v]+1)%2)//发现同性恋
{
flag=1;
}
}
else
{
combine_set(u,v);
}
}
}
printf("Scenario #%d:\n",kase++);
if(flag) printf("Suspicious bugs found!\n");
else printf("No suspicious bugs found!\n");
printf("\n");
}
return 0;
}