题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1272
并查集用来检测无向图的环是一个非常好的工具。
对于这道题,先要统计出有多少个顶点,假设有n个,再算出边的总数,如果n=m+1,那么满足题目要求。
关键是如果算出边数呢,而且算的同时又不能加那些会成环的边?我们可以用并查集维护,如果两个点有边相连,那么将它们连入同一个集合,并统计连入的边数,在连入之前先判断它们是否属于同一个集合,如何已经属于同一个集合那么这条边再连上去,就要成环了,所有这个时候就不能连上这条边。
边算出来,问题就解决了。
下面是AC代码:
#include<iostream>
using namespace std;
const int maxn=100005;
int fa[maxn],n,m,flag,vis[maxn],sum;
void init()
{
for(int i=0;i<maxn;i++) fa[i]=i;
}
int Find(int x)
{
if(fa[x]==x) return x;
return fa[x]=Find(fa[x]);
}
void Merge(int x,int y)
{
x=Find(x);
y=Find(y);
if(x==y) flag=1;
else fa[y]=x,sum++;//统计出现了多少不会成环的边
}
int main()
{
int x,y;
while(cin>>x>>y&&(x+y)!=-2)
{
init();
if( x==0 && y==0 ){ //为空树
cout<<"Yes"<<endl;
continue;
}
int cnt=0;flag=0;sum=0;
fill(vis,vis+maxn,0);
if(!vis[x]) vis[x]=1,cnt++;//统计出现了多少顶点
if(!vis[y]) vis[y]=1,cnt++;
Merge(x,y);
while(cin>>x>>y&&x+y)
{
if(!vis[x]) vis[x]=1,cnt++;
if(!vis[y]) vis[y]=1,cnt++;
Merge(x,y);
}
if(cnt==sum+1&&!flag) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}