题目大意是给你图的边的数据,问图是否是连通的且无环,满足输出yes,不满足输出no 。
用并查集就可以了,在联合2个节点的时候,若2个节点的祖先节点是相同的,说明在把这2个节点联合起来之前这2个节点就已经是连通的了,执行了联合这2个节点的操作后,就出现环了.需要注意的是坑点很多
#include<stdio.h>//用并查集判断无向图里是否有回路存在,用拓扑排序判断有向图是否存在回路
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
using namespace std;
#define maxn 100000+5
#define inf 0x3f3f3f3f
int par[maxn],vis[maxn]={0};
int flag=0;
int myfind(int x)
{
int t=x,tt;
while(par[t]!=t) t=par[t];
return t;
}
void unit(int x,int y)
{
x=myfind(x);
y=myfind(y);
if(x==y)
flag=1;
else
par[y]=x;
}
int main()
{
int u,v;
int cnt;
int maxx=0,minn=inf;
for(int i=1;i<maxn;i++)
par[i]=i;
while(scanf("%d%d",&u,&v)!=EOF)
{
if(u==-1&&v==-1) return 0;
if(u==0) {cout<<"Yes"<<endl;continue;}
for(int i=1;i<maxn;i++)
par[i]=i;
memset(vis,0,sizeof(vis));
flag=0;
maxx=0;
minn=inf;
vis[u]=vis[v]=1;
maxx=max(max(u,v),maxx);
minn=min(min(u,v),minn);
unit(u,v);
while(scanf("%d%d",&u,&v)!=EOF)
{
if(u==0&&v==0)
{
if(flag)
cout<<"No"<<endl;
else
{
cnt=0;
for(int i=minn;i<=maxx;i++)
if(vis[i]&&par[i]==i) cnt++;
if(cnt==1)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
break;
}
else
{
vis[u]=vis[v]=1;
maxx=max(max(u,v),maxx);
minn=min(min(u,v),minn);
if(u==v) flag=1;
if(!flag)
unit(u,v);
}
}
}
}