给出一堆边给你,让你判断这是不是一棵树。边的信息以(start , end)的形式给出.
A tree is a well-known data structure that is either empty (null, void, nothing) or is a set of one or more nodes connected by directed edges between nodes satisfying the following properties.

There is exactly one node, called the root, to which no directed edges point.
Every node except the root has exactly one edge pointing to it.
There is a unique sequence of directed edges from the root to each node.
For example, consider the illustrations below, in which nodes are represented by circles and edges are represented by lines with arrowheads. The first two of these are trees, but the last is not.

In this problem you will be given several descriptions of collections of nodes connected by directed edges. For each of these you are to determine if the collection satisfies the definition of a tree or not.

Input

The input will consist of a sequence of descriptions (test cases) followed by a pair of negative integers. Each test case will consist of a sequence of edge descriptions followed by a pair of zeroes Each edge description will consist of a pair of integers; the first integer identifies the node from which the edge begins, and the second integer identifies the node to which the edge is directed. Node numbers will always be greater than zero.

Output

For each test case display the line "Case k is a tree." or the line "Case k is not a tree.", where k corresponds to the test case number (they are sequentially numbered starting with 1).

Sample Input

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

Sample Output

Case 1 is a tree.
Case 2 is a tree.
Case 3 is not a tree.

方法一:直接使用树的定义来做。
    树的性质

        1)树的节点数比边数多1(空树除外)

        2) 树中除根节点的每个节点只有唯一的父节点。

      条件1可以排除有环的图,条件2可以排除多个根的图。

      特别注意的是,空树不满足条件1,需单独判断!

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int pre[100010];
int main()
{
int s=0;
while(1)
{
s++;
int x,y,s1=0,k=0;
memset(pre,0,sizeof(pre));
while(~scanf("%d%d",&x,&y)&&(x+y))
{
if(x==-1&&y==-1) return 0;
pre[x]=1;
pre[y]=1;
k++;
}
for(int i=0;i<100010;i++)
{
if(pre[i])
s1++;
}
if(s1==0||s1==k+1)//树的节点数比边数多1(空树除外)
printf("Case %d is a tree.\n",s);
else
printf("Case %d is not a tree.\n",s);
}
}

方法二:并查集

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int maxn = 1000; int p[maxn]; //存父亲节点
int r[maxn]; //存入度
bool used[maxn]; //判断下标是否使用
int Max, Min; //判断树中使用的下标的最值 void set() //初始化
{
for(int x = 0; x < maxn; x++)
{
p[x] = x; //自己为自己的父亲节点
r[x] = 0; //各点独立 入度为 0
used[x] = false; //各点均未使用
}
Min = maxn;
Max = -maxn;
} int find(int x) //找根节点
{
return x == p[x] ? x : p[x] = find(p[x]);
} void Union(int x, int y) //合并两点所在的树
{
int fx = find(x);
int fy = find(y);
p[fy] = fx;
}
int main()
{
int a, b;
int C = 0; //记录是第几组数据
while(scanf("%d%d", &a, &b) != EOF)
{
if(a == -1 && b == -1) break;
set(); //初始化 p[b] = a; r[b]++; //处理第一对数据
Min = min(a, b);
Max = max(a, b);
used[a] = true; //标记使用
used[b] = true; int x, y;
bool flag = true;
while(scanf("%d%d", &x, &y) != EOF)
{
if(x == 0 && y == 0)
{
int root = 0, index; //记录根节点个数 和下标
for(int i = Min; i <= Max; i++)
{
if(used[i] && i == p[i]) //判断有几个根
{
root++; index = i;
}
} if(root != 1) flag = false; //一棵树只能有一个根 if(flag)
{
for(int i = Min; i <= Max; i++) //判断入度情况,除了根节点,其它节点入度均为1
{
if(i != index && used[i] && r[i] != 1) flag = false;
}
} if(flag) printf("Case %d is a tree.\n", ++C);
else printf("Case %d is not a tree.\n", ++C);
//printf("%d\n", root); //开始有些小错误 输出中间变量,找错误
break; //注意:易忘记
} if(find(x) != find(y)) Union(x, y); //如果不在同一棵树中,则合并 r[y]++; //入度+1
used[x] = true; //标记使用
used[y] = true;
Min = min(Min, x); Min = min(Min, y); //更新最值
Max = max(Max, x); Max = max(Max, y);
}
}
return 0;
}

最新文章

  1. JQ实现accordion(可折叠)效果
  2. int和long int的区别
  3. 戴文的Linux内核专题:02源代码
  4. H5移动前端完美布局之padding
  5. PHP 优化详解
  6. CentOS(四)--Linux系统的启动级别
  7. javascript实现限制上传文件的大小
  8. [JavaScript] 判断键盘同时按某些键时执行操作。
  9. ArcEngine 添加字段
  10. 淘宝弹性布局方案lib-flexible研究
  11. hibernate 基本和简单易用
  12. C#通过接口与线程通信(捕获线程状态)介绍
  13. nodejs url方法
  14. Myeclipse插件将wsdl生成java客户端代码
  15. 热切换Log4j级别配置
  16. [Sdoi2017]相关分析 [线段树]
  17. xpath简单实用
  18. RISC-V平台的汇编指令解析
  19. JVM内存分配及GC流程
  20. AI 随机梯度下降(SGD)

热门文章

  1. 探索 .NET团队对API的设计流程
  2. C#处理医学图像(一):基于Hessian矩阵的血管肺纹理骨骼增强对比
  3. Django中一种常见的setting与账密保存/读取方式
  4. 图片质量评估论文 | 无监督SER-FIQ | CVPR2020
  5. pyi文件是干嘛的?(一文读懂Python的存根文件和类型检查)
  6. (十)Python装饰器
  7. Can&#39;t locate CPAN.pm in @INC
  8. 【EXPDP】Oracle expdp中并行问题
  9. java中如何踢人下线?封禁某个账号后使其会话立即掉线!
  10. poj-DNA排序