题目大意:输入每次两个数n,m,表示n->m有一条边,当输入0 0时表示一棵树输入完毕,开始判断。题目要求任意两个顶点之间只有一条路可以相通,并且输入的必须是一个树形结构,即有一个是根节点,入度为0。上图满足题目要求。
首先输入的边数肯定是顶点数减一,因为两个顶点之间只有一条路,并且除根节点之外所有节点的入度只能为1,输入的所有的点构成的只有一幅图,即不会有两处分开的图。
0 0 这组样例输出为满足,因为没有违反题目要求。
代码如下:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100050;
int pre[maxn],a[maxn];
void creat()
{
for(int i=0;i<=maxn;i++)
pre[i]=i;
}
int findroot(int root)
{
int son=root,tmp;
while(root!=pre[root])
root=pre[root];
while(son!=pre[son])
{
tmp=pre[son];
pre[son]=root;
son=tmp;
}
return root;
}
int main()
{
int n,m,x,y,cas=1,tmp,sum=0,num=0,flag=0;
creat();
while(scanf("%d %d",&n,&m)==2)
{
if(n<0&&m<0)break;
if(n==0&&m==0)
{
if(num==0)
printf("Case %d is a tree.\n",cas++);
else if(sum==num+1&&flag==0)
{
printf("Case %d is a tree.\n",cas++);
}
else
{
printf("Case %d is not a tree.\n",cas++);
}
memset(a,0,sizeof(a));
flag=0;
sum=0,num=0;
creat();
continue;
}
if(a[n]==0)
{
a[n]++;
sum++;
}
if(a[m]==0)
{
a[m]++;
sum++;
}
num++;
int root1=findroot(n);
int root2=findroot(m);
if(root2!=m||root1==root2) //root2不为m说明已经有别的点指向它,n再指向它肯定错,后面那个判断两个点是否已经在一个集合中已经在也错比如1 2 2 1
{
flag=1;
}
//printf("%d %d\n",num,flag);
pre[m]=root1;
}
return 0;
}