题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=129 树的判定
关于树,即只有一个根节点,也即根节点的入度为0,其它点入度为1;代码如下:
#include<stdio.h>
#include<string.h>
const int N=1e4+5;
int father[N],rank[N],visit[N],in[N];
void init()
{
for(int i=0; i<N; i++)
{
rank[i]=1;//秩初始化
father[i]=i;//父节点初始化
in[i]=0;//入度初始化
}
}
int find(int n)
{
if(n==father[n]) return n;
return find(father[n]);//路径压缩查找
}
bool merge(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx==fy) return false;
if(rank[fx]>=rank[fy])//按秩合并
{
father[fy]=fx;
rank[fx]+=rank[fy];
}
else
{
father[fx]=fy;
rank[fy]+=rank[fx];
}
return true;
}
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int a,b,i,tot=1;
while(scanf("%d%d",&a,&b)&&a!=-1&&b!=-1)
{
memset(visit,0,sizeof(visit));
if(a==0&&b==0)
{
printf("Case %d is a tree.\n",tot++);
continue;
}
bool flog=true;
int maxx=0;
maxx=max(maxx,max(a,b));
init();
visit[a]=1;
visit[b]=1;
flog=merge(a,b);
in[b]++;//b点的入度加1
while(scanf("%d%d",&a,&b)&&a&&b)
{
if(!flog) continue;
in[b]++;//由于给定定的a,b是有向的,即b为树叶
visit[a]=1;
visit[b]=1;
flog=merge(a,b);
maxx=max(maxx,max(a,b));
}
printf("Case %d ",tot++);
if(flog)
{
int cnt=0;
for(i=1; i<=maxx; i++)
{
if(visit[i]&&father[i]==i)
cnt++;
if(cnt>1)//一棵树只有一个根节点,即father[i]==i
{
flog=false;
break;
}
}
cnt=0;
for(i=1; i<=maxx; i++)
{
if(visit[i]&&in[i]==0)
cnt++;
}
if(cnt>1) //一棵树只有根节点的入度为0,其他点入度为1
flog=false;
}
printf(flog?"is a tree.\n":"is not a tree.\n");
}
}