判断给定的结点是否构成一棵树。
注意:结点集合为空构成空树;有重复的边不是树;节点有指向自己的边不是树;树只有一个根节点;
思想:使用并查集。将添加的结点合并,最终只有一个结点。注意新加的结点b为a的长辈。
#include <iostream>
//#include <map>
using namespace std;
/*
tree: 1. no cycle
2. noly indegree==0
3. else indegree==1
*/
const int size = 100000;
//map<int, int> hash;
int fa[size];
bool vis[size];
int Find(int x)
{
if (x == fa[x])
return x;
return fa[x] = Find(fa[x]);
}
int main()
{
int a, b;
int cas = 1;
int yes = 1;
int i, maxn;
while (scanf("%d %d",&a,&b)!=EOF)
{
if (a < 0 || b < 0) break;
if (0 == a && 0 == b)// 空树
{
printf("Case %d is a tree.\n",cas++);
continue;
}
yes = 1;
maxn = 0;
for (i = 0; i < size; ++i)
{
fa[i] = i;
vis[i] = 0;
}
if (a != b)
fa[b] = a;
else yes = 0; // self-directed
vis[b] = vis[a] = 1;
maxn = a > b? a :b;
while (scanf("%d %d",&a,&b)!=EOF)
{
if (0 == a || 0 == b)
break;
if (!yes || a== b)
{
yes = 0; // self-directed
continue;
}
vis[a] = vis[b] = 1;
maxn = maxn>a?maxn:a;
maxn = maxn>b?maxn:b;
if (fa[b] != b || Find(a) == Find(b)) //b has more fa, b is a's father
{
yes = 0;
//break;
}
else fa[b] = Find(a);
}
a = 0;
for (i = 1; i <= maxn; ++i)
{
if (vis[i])
{
if (Find(i) == i)
a++;
if (a > 1)
{
yes = 0;
break;
}
}
}
if (a != 1) yes = 0;
printf("Case %d is ",cas++);
if (yes) printf("a tree.\n");
else printf("not a tree.\n");
}
//system("pause");
return 0;
}