题目描述
树是众所周知的数据结构。
它有可能是空的或者是由满足以下属性的节点之间的有向边连接的一个或多个节点的集合:
只有一个根节点,没有有向边指向根节点。
根之外的每个节点都只有一个指向该节点的边。
从根到每个节点有且仅有一个有向边序列。
例如,下图前两个是树,最后一个不是树。
输入
输入将包含多组测试用例。
每个测试用例将包含一系列有向边。
每条边由一对整数组成; 第一个整数是有向边开始的节点,第二个整数是有向边指向的节点。 结点编号 1=<n<=1000。
以一对0结束一个测试用例。
以两个-1结束输入。
输出
对于每组输入,若该集合是一棵树,输出 “Case k is a tree.”
若该集合不是一棵树,输出"Case k is not a tree."
样例输入
6 8 5 3 5 2 6 4
5 6 0 0
8 1 7 3 6 2 8 9 7 5
7 4 7 8 7 6 0 0
3 8 6 8 6 4
5 3 5 6 5 2 0 0
-1 -1
样例输出
Case 1 is a tree.
Case 2 is a tree.
Case 3 is not a tree.
注意 0 0(空树)的情况
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1005;
vector<int>g[maxn];
int indegree[maxn];
int v[maxn];
bool judge()
{//无环,只有一个根结点,一个节点最多只有一个入度
queue<int>q;
int root=0,num=0,sum=0,flag=0;
for(int i=0;i<maxn;i++)
if(v[i]) sum++;
for(int i=0;i<maxn;i++)
if(v[i]&&indegree[i]==0)
{
root++;
num++;
q.push(i);
}
if(root!=1) return false;
while(!q.empty())
{
int u=q.front(); q.pop();
for(int i=0;i<g[u].size();i++)
{
indegree[g[u][i]]--;
if(indegree[g[u][i]]!=0) return false;
num++;
q.push(g[u][i]);
}
}
if(num!=sum) return false;
return true;
}
int main()
{
int a,b,cnt=0;
while(scanf("%d%d",&a,&b)!=EOF)
{
if(a==-1&&b==-1) break;
if(a==0&&b==0) printf("Case %d is a tree.\n",++cnt);
else
{
memset(indegree,0,sizeof indegree);
memset(v,0,sizeof v);
for(int i=0;i<maxn;i++)
g[i].clear();
while(a!=0&&b!=0)
{
g[a].push_back(b);
indegree[b]++;
v[a]=1,v[b]=1;
scanf("%d%d",&a,&b);
}
if(judge()) printf("Case %d is a tree.\n",++cnt);
else printf("Case %d is not a tree.\n",++cnt);
}
}
return 0;
}