// 题意: 给出一些边,由所给出的边能否构成一棵树.(节点数<100)
// 思路: n个顶点的树具有3个特点:连通,不含环,恰好包含n-1条边.只要有任意两个,就能推导出第3个
// 所以我们可以通过是否连通和不含环来判断可以构成树.
// 不含环: 通过并查集,如果边a->b, a和b的祖先结点都一样,则是有环,包括a->a,和 a->b 重复出现,
// 连通: 只有一个根结点
#include <iostream> //并查集
using namespace std;
#define maxn 1000
int p[maxn],isNode[maxn];
int find(int x)
{
return p[x]==x ? x : p[x]=find(p[x]);
}
int main()
{
int t=1,a,b;
while(cin>>a>>b&&a!=-1) // a->b
{
if(a==0) //只有 0 0 ,空树也是一棵树
{
printf("Case %d is a tree.\n",t++);
continue;
}
for(int i=1;i<maxn;++i)
{
p[i]=i;
isNode[i]=0;
}
int isTree=1,tail=0;
while(a!=0)
{
if(isTree)
{
int x=find(a),y=find(b);
if(x==y) //说明存在环
{
isTree=0;
}
else
{
p[y]=x; //a->b
isNode[a]=isNode[b]=1; //标志结点
tail=max(tail,max(a,b)); //结点的下标并不是顺序增加 1
}
}
cin>>a>>b;
}
if(!isTree)
printf("Case %d is not a tree.\n",t++);
else
{
int roots=0;
for(int i=1;i<=tail;i++)
{
if(isNode[i]&&p[i]==i) //找到一根结点
{
roots++;
if(roots>1)
break;
}
}
if(roots==1)
printf("Case %d is a tree.\n",t++);
else
printf("Case %d is not a tree.\n",t++); //没有根结点,或者不只一个根结点
}
}
return 0;
}