题目链接:poj1308
题目的要求是让判断给出的点能否连接成一颗树,一棵树的话就只有一个树根,同时一个子节点不能同时拥有两个父亲,解法是用并查集,用father数组来记录每个节点的父节点,v数组来记录是否输入了节点。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
int father[100],v[100];
void set()
{
for(int i = 0; i < 100; i ++)
father[i] = i, v[i] = 0;
}
int find_father(int x)
{
if(father[x] != x)
{
father[x] = find_father(father[x]);
}
return father[x];
}
int main()
{
int i,x,y,p = 1;
while(scanf("%d%d",&x,&y), x !=-1 && y != -1)
{
if(!x && !y)//空树也是树,真心坑人。。
{
printf("Case %d is a tree.\n",p++);
continue;
}
set();
father[y] = x;
v[x] = v[y] = 1;
int flag = 1;
if(x == y) flag = 0;//两个数相等表示同一点指向自己,不是树
while(scanf("%d%d",&x,&y),x&&y)
{
if(!flag) continue;
v[x] = v[y] = 1;
if(father[y] != y) flag = 0;//表示该节点已经有父节点了
int fun = find_father(x);
if(fun == y) flag = 0;//如果x的父节点是y,不能构成树,列如1 2 2 1 0 0
else father[y] = fun;
}
if(!flag)
{
printf("Case %d is not a tree.\n",p++);
continue;
}
int num = 0;
for(i = 0; i < 100; i ++)
{
if(v[i] && father[i] == i)
{
num ++;//表示根的数量
}
}
if(num > 1)
printf("Case %d is not a tree.\n",p++);
else
printf("Case %d is a tree.\n",p++);
}
return 0;
}