并查集。
该题只要成立2个条件,则输出Yes(输出请注意大小写)。
第一个条件是该图中没有环。
第二个条件是并查集只有一个集合。
构成环的条件是2个点已经是在相同的集合里,但是让他们再并成一个集合,这样就构成了环。
小心测试数据 0 0 Yes 1 1 0 0 Yes
#include<cstdio>
#include<iostream>
using namespace std;
#define maxn 100005
int father[maxn],rank[maxn],n=maxn-2;
void makeset()
{
int i;
for(i=1;i<=n;i++)
father[i]=-1;//标记节点没被用到
rank[i]=0;
}
int getfather(int v)
{
if(father[v]==v)
return v;
else
father[v]= getfather(father[v]);
return father[v];
}
bool same(int a,int b)
{
if(getfather(a)==getfather(b))
return 1;
return 0;
}
void Union(int a,int b)
{
if(same(a,b))
return ;
else
father[getfather(a)]=b;
}
void judge(int a,int b)
{
if(rank[getfather(a)]>rank[getfather(b)])
father[getfather(b)]=getfather(a);
else
{
father[getfather(a)]=getfather(b);
if(rank[getfather(a)]==rank[getfather(b)])
rank[getfather(b)]++;
}
}
int main()
{
int a,b,i,j;
int flag;
while(scanf("%d%d",&a,&b)!=EOF&&a!=-1&&b!=-1)
{
makeset();
flag=1;
if(a==0&&b==0)
{
printf("Yes\n");
continue;
}
if(father[a]<0)
father[a]=a;
if(father[b]<0)
father[b]=b;
if(a!=b)
if(same(a,b))
flag=0;
if(flag)
{
Union(a,b);
judge(a,b);
}
while(scanf("%d%d",&a,&b)&&(a!=0&&b!=0))
{
if(father[a]<0)
father[a]=a;
if(father[b]<0)
father[b]=b;
if(same(a,b))
flag=0;
if(flag)
{
Union(a,b);
judge(a,b);
}
}
int Flag=1,k;
for(i=1;i<=n;i++)
if(getfather(i)>0)
{
k=getfather(i);
break;
}
for(;i<=n;i++)
{
if(father[i]>0&&k!=getfather(i))
{
Flag=0;
break;
}
}
if(flag&&Flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}