主题思想: 判断连通分量,有没有环,是不是最小生成树。
判断连通分量可以用并查集来做,如果新来一条边,这条边的两个端点的根是同一个,那么加上这条边后,和根就会构成一个环,如果要输出环,可以采用dfs+ stack的方式把构成环的节点压入栈。 如果没有环,只有一个连通分量,边的个数+1 等于顶点的个数,那么就是最小生成树。
针对这道题,还要注意处理输入数据可能是0 0 并以0 0 表示这组数据的结束,0 0 表示空树,要输出yes
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int maxn=100005;
int a[maxn];
bool hascycle=false;
int visited[maxn];
int en; //edge num;
int vn;
int Find(int x){
if(a[x]==x)
return a[x];
else a[x]=Find(a[x]);
return a[x];
}
void UN(int p,int q){
p=Find(p);
q=Find(q);
if(p==q){
hascycle=true;
}else{
a[p]=q;
en++;
}
return ;
}
void init(){
en=0;
vn=0;
for(int i=0;i<maxn;i++){
a[i]=i;
visited[i]=false;
hascycle=false;
}
}
int main(){
int c,d;
init();
bool flag=false;
while(true){
init();
scanf("%d%d",&c,&d);
if(c==-1&&d==-1) break;
if(c==0&&d==0){
printf("Yes\n");
continue;
}
visited[c]=true;
visited[d]=true;
UN(c,d);
while(true){
scanf("%d%d",&c,&d);
if(c==0&&d==0) break;
visited[c]=true;
visited[d]=true;
UN(c,d);
}
for(int i=0;i<maxn;i++){
if(visited[i]) vn++;
}
if(!hascycle&&en+1==vn)printf("Yes\n");
else printf("No\n");
}
return 0;
}