#include <iostream>
using namespace std;
//题意:和题目1272类似,判断给定的有向图是不是一颗树
//思路:树的定义:或着是一颗空树,或者为一颗非空树,只有一个根节点,其他的节点构成了m(m > 0)个
// 互不相交的有限集合,每一个集合本身又是一颗树
//判断方法:1、或者为一颗空树
// 2、对于一颗非空树,只有一个根节点,该节点的入度为0,其他的每一个定点的入度为1
// 3、并且不能有环,即n个节点只能有n-1条边
#define NSIZ 100010
int parent[NSIZ];
int myrank[NSIZ];
int flag[NSIZ];
int degree[NSIZ];
void make_set(int n)
{
int i;
memset(flag, 0, sizeof(flag));
memset(degree, 0, sizeof(degree));
for(i = 1;i < n; ++i)
{
parent[i] = i;
myrank[i] = 1;
}
}
int find_set(int x)
{
if(x != parent[x])
{
parent[x] = find_set(parent[x]);
}
return parent[x];
}
void union_set(int x, int y)
{
x = find_set(x), y = find_set(y);
if(x != y)
{
if(myrank[x] < myrank[y])
{
parent[x] = y;
myrank[y] += myrank[x];
}
else
{
parent[y] = x;
myrank[x] += myrank[y];
}
}
}
int main()
{
int n, m;
int i, t = 1, x, y, fx, fy;
int minD,maxD;
int isOK;
while(scanf("%d %d", &x, &y) != EOF && x > 0 && y > 0)
{
if(!x && !y)
{
printf("Case %d is a tree.\n", t++);
continue;
}
//init
make_set(NSIZ);
isOK = 0;
minD = min(x, y);
maxD = max(x, y);
do
{
minD = min(minD, min(x, y));
maxD = max(maxD, max(x, y));
flag[x] = 1;
flag[y] = 1;
fx = find_set(x);
fy = find_set(y);
degree[y]++;
if(fx == fy)
{
isOK = -1; //标志图中有环
}
else
{
if(degree[y] > 1) //非根节点入度必须为1
{
isOK = -1;
}
union_set(x, y);
}
}while(scanf("%d %d", &x, &y) != EOF && (x + y));
//图中无环时,看看图是否是连同的,如果不是连同的则会有至少2个根节点
if(!isOK)
{
for(i = minD; i <= maxD; ++i)
{
if(flag[i] && i == find_set(i))
{
isOK++;
}
}
}
if(isOK == 1)
{
printf("Case %d is a tree.\n", t++);
}
else
{
printf("Case %d is not a tree.\n", t++);
}
}
return 0;
}
hdu1325Is It A Tree?【并差集】
最新推荐文章于 2021-04-20 10:56:04 发布