并查集的运用,不过有一些变化
首先必须弄清楚构成树的条件:
1、无环,在这里,可直接用并查集判断。
2、连通,也就是最后只有一个连通分量。
3、除了根结点,每个点有且仅有一个父结点。这个条件我一开始忽略了。。
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX =100005;
int last[MAX];
char have[MAX];
void make(){
for(int i=1;i<=MAX;i++){
last[i]=i,have[i]=0;
}
}
int find(int x){
int p=x,t;
while(p!=last[p])p=last[p];
while(x!=p){
t=last[x],last[x]=p,x=t;
}
return p;
}
void un(int a,int b){
last[a]=b;
}
int main(){
int a,b,aa,bb,cases=1,ok=1,all=0,node,edge=0;
make();
while(1){
scanf("%d %d",&a,&b);
all++;
if(a==0&&a==b){
if(all==1){
printf("Case %d is a tree.\n",cases++);
all=0;
continue;
}
if(ok){
node=0;
for(int i=1;i<=MAX;i++)
if(have[i])
node++;
if(node-1!=edge)
ok=0;
}
if(ok)
printf("Case %d is a tree.\n",cases++);
else
printf("Case %d is not a tree.\n",cases++);
ok=1,edge=0,make(),all=0;
continue;
}
if(a<0&&b<0)
break;
if(ok){
have[a]=a,have[b]=1;
aa=find(a),bb=find(b);
if(bb!=b){
ok=0;
continue;
}
if(aa!=bb){
un(bb,aa);
edge++;
}
else
ok=0;
}
}
}