nyoj129 (判定树)
如何判定是否为树
1.树可以认为是(有向图)的特殊情况
(1).入度为一(2).无环树:(3).只有一个根节点
所以要进行如下判断
1.输入的两个数是否构成环
(1).自身成环e.g.(2-2)
(2).间接成环e.g.old:[(1-2),(1-3)], new[(2-3)]
输入的第二个数是否已经有father e.g.(1-2),(3-2)
3.根节点是否相同(是否是一棵树,从属于一个集合)
采用数据结构:并查集(查找,合并集合)
因为一棵树的所有节点从属于一个集合也就是所有节点(除根节点)都属于根节点所在的集合
入度的判断就是看看新输入的第二个数是不是已经在一个集合中
--------------------------------------------------------------------------------------------------
源码
#include <stdio.h>
#include <memory.h>
int up[10005], down[10005], father[10005];
int find(int x)
{
if (father[x] == -1)
{
return x;
}
return find(father[x]);
}
void unionset(int x, int y)
{
father[y] = x;
}
int main()
{
int x, y;
int count, tc = 1;
while (1)
{
memset(father, -1, sizeof(father));
memset(up, 0, sizeof(up));
memset(down, 0, sizeof(down));
scanf("%d%d", &x, &y);
if (x==-1 && y == -1)
{
break;
}
if ((x || y) == 0)
{
printf("Case %d is a tree.\n", tc++);
continue;
}
count = 0;
up[count] = x;
down[count] = y;
while (scanf("%d%d", &x, &y), x&&y)
{
count++;
up[count] = x;
down[count] = y;
}
bool flag = true;
for (int j=0; j<=count; ++j) // 判断环,入度为1
{
x = find(up[j]); // 查找father
y = find(down[j]); // 查找father
if (x==y || y != down[j])
// (1)up[j]和down[j]都没有father 相等自身形成环 e.g.(1-1)
// (2)father(x=y)相同(如果联合x,y,就会形成环 e.g.(1-2),(1-3),(2-3)),
// (3)y已经有father(判断入度是否为1(树入度为1)) e.g. (1-2),(3-2)
{
flag = false;
break;
}
unionset(x, y);
}
if (!flag)
{
printf("Case %d is not a tree.\n", tc++);
continue;
}
x = find(down[0]);
flag = true;
for (int i=1; i<=count; ++i) //判断是不是一颗树(根节点是否相同)
{
if (x != find(down[i]))
{
flag = false;
break;
}
}
if (flag)
{
printf("Case %d is a tree.\n", tc++);
}
else
{
printf("Case %d is not a tree.\n", tc++);
}
}
return 0;
}