题目1481:Is It A Tree?

来源:互联网 发布:增值税发票模拟软件 编辑:程序博客网 时间:2024/06/06 00:27

题目描述:

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.

输入:

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 and less than 10000.

输出:

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).

样例输入:
6 8  5 3  5 2  6 45 6  0 08 1  7 3  6 2  8 9  7 57 4  7 8  7 6  0 03 8  6 8  6 45 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.


本以为停简单的一道题,但是too young,too simple了,考虑的情况一直不周全。

借鉴了网上大牛的代码,主要有两种思路:

1.找根结点(处理的时候要格外小心,参见下面的代码,可以去掉2->1,3->4->5->3的情形),配合“顶点数等于边数加1”这个公式来判断。

2.利用拓扑排序,配合非根结点的入度为1,入度为0的结点只有一个,来进行判断。

当时还想利用入度为0的结点只有一个配合“顶点数等于边数加1”来进行判断,但一直错误,忽略了2->1,3->4->5->3的情形。

下面的代码主要是利用第一种思路修改而成,至于第二种思路的实现方法参考http://blog.csdn.net/newner/article/details/8655083

另注:九度OJ上的判题系统没有2->3,4->3这种情形进行判断,故网上有的算法对此情形判断失败后仍能AC,我也被坑了好久。


#include<stdio.h>#include<string.h>int root[10001];bool visited[10001];int find(int x) {if (root[x] == x)return x;else {int tmp = find(root[x]);root[x] = tmp;return tmp;}}int main() {int cas = 0;int a, b;int edges = 0;int nodes = 0;bool flag = true;while (scanf("%d%d", &a, &b) != EOF) {if (a < 0 && b < 0)break;if (a == 0 && b == 0) {cas++;int inNum = 0;if (nodes != 0 && nodes - edges != 1)flag = false;if (flag)printf("Case %d is a tree.\n", cas);elseprintf("Case %d is not a tree.\n", cas);edges = nodes = 0;flag = true;for (int i = 1; i < 10001; i++)root[i] = i;memset(visited, false, sizeof(visited));continue;}//这一步非常关键,排除掉a->b,c->b的情形,否则会出错,还可防止出现环路,还有a->aif (find(b) == b && find(a) != b)root[b] = a;elseflag = false;if (!visited[a]) {visited[a] = true;nodes++;}if (!visited[b]) {visited[b] = true;nodes++;}edges++;}return 0;}
题目链接:

http://ac.jobdu.com/problem.php?pid=1481

其他正文中未指出的参考链接:

http://www.cnblogs.com/qwertWZ/p/3565827.html

http://www.itdadao.com/articles/c15a405263p0.html

0 0