九度oj 题目1481:Is It A Tree?

题目描述:

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

一开始的代码如下
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <map>
 5 #include <iostream>
 6 using namespace std;
 7
 8 int par[10002];
 9 int height[10002];
10
11 void init() {
12     for (int i = 0; i < 10002; i++) {
13         par[i] = i;
14         height[i] = 0;
15     }
16 }
17
18 int find(int t) {
19     if (par[t] == t) {
20         return t;
21     }
22     return par[t] = find(par[t]);
23 }
24
25 void unite(int x, int y) {
26     x = find(x);
27     y = find(y);
28     if (x == y) {
29         return;
30     }
31     else {
32         if (height[x] < height[y]) {
33             par[x] = y;
34         }
35         else {
36             par[y] = x;
37             if (height[x] == height[y]) {
38                 height[x]++;
39             }
40         }
41     }
42 }
43
44 bool isA(int p) {
45     int root = find(0);
46     for (int i = 1; i < p; i++) {
47         if (find(i) != root) {
48             return false;
49         }
50     }
51     return true;
52 }
53
54 map<int, int> mapping;
55
56 int main() {
57     //freopen("input.txt", "r", stdin);
58     //freopen("output.txt", "w", stdout);
59     int a, b;
60     int caseCnt = 0;
61     while (scanf("%d %d", &a,&b) != EOF && !(a == -1 && b ==-1)) {
62         int p = 0;
63         int cnt = 1;
64         init();
65         mapping.clear();
66         caseCnt++;
67         if (mapping.find(a) == mapping.end()) {
68             mapping[a] = p++;
69         }
70         if (mapping.find(b) == mapping.end()) {
71             mapping[b] = p++;
72         }
73         unite(mapping[a], mapping[b]);
74         while (scanf("%d %d", &a, &b) && !(a == 0 && b == 0)) {
75             if (mapping.find(a) == mapping.end()) {
76                 mapping[a] = p++;
77             }
78             if (mapping.find(b) == mapping.end()) {
79                 mapping[b] = p++;
80             }
81             unite(mapping[a], mapping[b]);
82             cnt++;
83         }
84         bool flag = isA(p);
85         flag = flag && (cnt == p - 1);
86         if (flag) {
87             printf("Case %d is a tree.\n", caseCnt);
88         }
89         else {
90             printf("Case %d is not a tree.\n", caseCnt);
91         }
92
93     }
94     return 0;
95 }

一开始思路比较简单,考虑如果图是连通的,那么如果边数为端点数减1,那么就是树

提交错误

开始没有考虑到可能有重边的情况,比如有两条a到b的边,或存在a到a的边,因此加一个判断,代码如下

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <map>
  5 #include <iostream>
  6 using namespace std;
  7
  8 int par[10002];
  9 int height[10002];
 10
 11 void init() {
 12     for (int i = 0; i < 10002; i++) {
 13         par[i] = i;
 14         height[i] = 0;
 15     }
 16 }
 17
 18 int find(int t) {
 19     if (par[t] == t) {
 20         return t;
 21     }
 22     return par[t] = find(par[t]);
 23 }
 24
 25 void unite(int x, int y) {
 26     x = find(x);
 27     y = find(y);
 28     if (x == y) {
 29         return;
 30     }
 31     else {
 32         if (height[x] < height[y]) {
 33             par[x] = y;
 34         }
 35         else {
 36             par[y] = x;
 37             if (height[x] == height[y]) {
 38                 height[x]++;
 39             }
 40         }
 41     }
 42 }
 43
 44 bool isSame(int x, int y) {
 45     x = find(x);
 46     y = find(y);
 47     if (x == y) {
 48         return true;
 49     }
 50     else {
 51         return false;
 52     }
 53 }
 54
 55 bool isA(int p) {
 56     int root = find(0);
 57     for (int i = 1; i < p; i++) {
 58         if (find(i) != root) {
 59             return false;
 60         }
 61     }
 62     return true;
 63 }
 64
 65 map<int, int> mapping;
 66
 67 int main() {
 68     //freopen("input.txt", "r", stdin);
 69     //freopen("output.txt", "w", stdout);
 70     int a, b;
 71     int caseCnt = 0;
 72     while (scanf("%d %d", &a,&b) != EOF && !(a == -1 && b ==-1)) {
 73         int p = 0;
 74         int cnt = 1;
 75         init();
 76         mapping.clear();
 77         caseCnt++;
 78         if (mapping.find(a) == mapping.end()) {
 79             mapping[a] = p++;
 80         }
 81         if (mapping.find(b) == mapping.end()) {
 82             mapping[b] = p++;
 83         }
 84         unite(mapping[a], mapping[b]);
 85         bool flag = true;
 86         while (scanf("%d %d", &a, &b) && !(a == 0 && b == 0)) {
 87             if (mapping.find(a) == mapping.end()) {
 88                 mapping[a] = p++;
 89             }
 90             if (mapping.find(b) == mapping.end()) {
 91                 mapping[b] = p++;
 92             }
 93             if (isSame(a, b)) {
 94                 flag = false;
 95                 break;
 96             }
 97             unite(mapping[a], mapping[b]);
 98             cnt++;
 99         }
100         flag = flag && isA(p);
101         flag = flag && (cnt == p - 1);
102         if (flag) {
103             printf("Case %d is a tree.\n", caseCnt);
104         }
105         else {
106             printf("Case %d is not a tree.\n", caseCnt);
107         }
108
109     }
110     return 0;
111 }

在93行增加了一段代码,用于判断这种情况,提交依然错误。

又注意到题目中的边是有方向的,

比如5->6, 7->6 我的代码就判断不了

而且95行break掉会少读入数据

于是立马修改

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <map>
  5 #include <iostream>
  6 using namespace std;
  7
  8 int par[10002];
  9 int height[10002];
 10 int cntD[10002];
 11
 12 void init() {
 13     for (int i = 0; i < 10002; i++) {
 14         par[i] = i;
 15         height[i] = 0;
 16     }
 17 }
 18
 19 int find(int t) {
 20     if (par[t] == t) {
 21         return t;
 22     }
 23     return par[t] = find(par[t]);
 24 }
 25
 26 void unite(int x, int y) {
 27     x = find(x);
 28     y = find(y);
 29     if (x == y) {
 30         return;
 31     }
 32     else {
 33         if (height[x] < height[y]) {
 34             par[x] = y;
 35         }
 36         else {
 37             par[y] = x;
 38             if (height[x] == height[y]) {
 39                 height[x]++;
 40             }
 41         }
 42     }
 43 }
 44
 45 bool isSame(int x, int y) {
 46     x = find(x);
 47     y = find(y);
 48     if (x == y) {
 49         return true;
 50     }
 51     else {
 52         return false;
 53     }
 54 }
 55
 56 bool isA(int p) {
 57     int root = find(0);
 58     for (int i = 1; i < p; i++) {
 59         if (find(i) != root) {
 60             return false;
 61         }
 62     }
 63     return true;
 64 }
 65
 66 map<int, int> mapping;
 67
 68 int main() {
 69     //freopen("input.txt", "r", stdin);
 70     //freopen("output.txt", "w", stdout);
 71     int a, b;
 72     int caseCnt = 0;
 73     while (scanf("%d %d", &a,&b) != EOF && !(a == -1 && b ==-1)) {
 74         int p = 0;
 75         int cnt = 1;
 76         init();
 77         mapping.clear();
 78         memset((void*)cntD, 0, sizeof(cntD));
 79         caseCnt++;
 80         if (mapping.find(a) == mapping.end()) {
 81             mapping[a] = p++;
 82         }
 83         if (mapping.find(b) == mapping.end()) {
 84             mapping[b] = p++;
 85         }
 86         cntD[mapping[b]]++;
 87
 88         unite(mapping[a], mapping[b]);
 89         bool flag = true;
 90         while (scanf("%d %d", &a, &b) && !(a == 0 && b == 0)) {
 91             if (flag == false) {
 92                 continue;
 93             }
 94             if (mapping.find(a) == mapping.end()) {
 95                 mapping[a] = p++;
 96             }
 97             if (mapping.find(b) == mapping.end()) {
 98                 mapping[b] = p++;
 99             }
100             if (cntD[mapping[b]] == 1) {
101                 flag = false;
102                 continue;
103             }
104             if (isSame(a, b)) {
105                 flag = false;
106                 continue;
107             }
108             cntD[mapping[b]]++;
109             unite(mapping[a], mapping[b]);
110             cnt++;
111         }
112         flag = flag && isA(p);
113         flag = flag && (cnt == p - 1);
114         if (flag) {
115             printf("Case %d is a tree.\n", caseCnt);
116         }
117         else {
118             printf("Case %d is not a tree.\n", caseCnt);
119         }
120
121     }
122     return 0;
123 }

增加了一个记录每个端点入度的数组,如果其值大于1,那么就不是一颗树。

提交依然错误。。。。

。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。

浏览了一下题解,终于发现问题

注意到题目第一行

A tree is a well-known data structure that is either empty (null, void, nothing)

树可以是空的,

也就是说如果他直接输入0 0,你要告诉它这是一棵树

再次修改代码

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <map>
  5 #include <iostream>
  6 using namespace std;
  7
  8 int par[10002];
  9 int height[10002];
 10 int cntD[10002];
 11
 12 void init() {
 13     for (int i = 0; i < 10002; i++) {
 14         par[i] = i;
 15         height[i] = 0;
 16     }
 17 }
 18
 19 int find(int t) {
 20     if (par[t] == t) {
 21         return t;
 22     }
 23     return par[t] = find(par[t]);
 24 }
 25
 26 void unite(int x, int y) {
 27     x = find(x);
 28     y = find(y);
 29     if (x == y) {
 30         return;
 31     }
 32     else {
 33         if (height[x] < height[y]) {
 34             par[x] = y;
 35         }
 36         else {
 37             par[y] = x;
 38             if (height[x] == height[y]) {
 39                 height[x]++;
 40             }
 41         }
 42     }
 43 }
 44
 45 bool isSame(int x, int y) {
 46     x = find(x);
 47     y = find(y);
 48     if (x == y) {
 49         return true;
 50     }
 51     else {
 52         return false;
 53     }
 54 }
 55
 56 bool isA(int p) {
 57     int root = find(0);
 58     for (int i = 1; i < p; i++) {
 59         if (find(i) != root) {
 60             return false;
 61         }
 62     }
 63     return true;
 64 }
 65
 66 map<int, int> mapping;
 67
 68 int main() {
 69     //freopen("input.txt", "r", stdin);
 70     //freopen("output.txt", "w", stdout);
 71     int a, b;
 72     int caseCnt = 0;
 73     while (scanf("%d %d", &a,&b) != EOF && !(a == -1 && b ==-1)) {
 74         int p = 0;
 75         int cnt = 1;
 76         init();
 77         mapping.clear();
 78         memset((void*)cntD, 0, sizeof(cntD));
 79         caseCnt++;
 80
 81         if (a == 0 && b == 0) {
 82             printf("Case %d is a tree.\n", caseCnt);
 83             continue;
 84         }
 85         if (mapping.find(a) == mapping.end()) {
 86             mapping[a] = p++;
 87         }
 88         if (mapping.find(b) == mapping.end()) {
 89             mapping[b] = p++;
 90         }
 91         cntD[mapping[b]]++;
 92
 93         unite(mapping[a], mapping[b]);
 94         bool flag = true;
 95         while (scanf("%d %d", &a, &b) && !(a == 0 && b == 0)) {
 96             if (flag == false) {
 97                 continue;
 98             }
 99             if (mapping.find(a) == mapping.end()) {
100                 mapping[a] = p++;
101             }
102             if (mapping.find(b) == mapping.end()) {
103                 mapping[b] = p++;
104             }
105             if (cntD[mapping[b]] == 1) {
106                 flag = false;
107                 continue;
108             }
109             if (isSame(a, b)) {
110                 flag = false;
111                 continue;
112             }
113             cntD[mapping[b]]++;
114             unite(mapping[a], mapping[b]);
115             cnt++;
116         }
117         flag = flag && isA(p);
118         flag = flag && (cnt == p - 1);
119         if (flag) {
120             printf("Case %d is a tree.\n", caseCnt);
121         }
122         else {
123             printf("Case %d is not a tree.\n", caseCnt);
124         }
125
126     }
127     return 0;
128 }

提交终于通过了。

还是要仔细读题呀!!!!!

后来又想到是不是直接判断入度即可判断出它是不是一棵树,写出了如下代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <map>
 5 #include <iostream>
 6 using namespace std;
 7
 8 int cntD[10002];
 9
10 map<int, int> mapping;
11
12 bool isTree(int p) {
13     int t = 0;
14     for(int i = 0; i < p; i++) {
15         if(cntD[i] == 0) {
16             t++;
17             if(t > 1) {
18                 return false;
19             }
20         }
21         else if(cntD[i] != 1) {
22             return false;
23         }
24     }
25     if(t == 0) {
26         return false;
27     }
28     return true;
29 }
30 int main() {
31     //freopen("input.txt", "r", stdin);
32     //freopen("output.txt", "w", stdout);
33     int a, b;
34     int caseCnt = 0;
35     while (scanf("%d %d", &a,&b) != EOF && !(a == -1 && b ==-1)) {
36         int p = 0;
37         int cnt = 1;
38         mapping.clear();
39         memset((void*)cntD, 0, sizeof(cntD));
40         caseCnt++;
41
42         if (a == 0 && b == 0) {
43             printf("Case %d is a tree.\n", caseCnt);
44             continue;
45         }
46         if (mapping.find(a) == mapping.end()) {
47             mapping[a] = p++;
48         }
49         if (mapping.find(b) == mapping.end()) {
50             mapping[b] = p++;
51         }
52         cntD[mapping[b]]++;
53
54         bool flag = true;
55         while (scanf("%d %d", &a, &b) && !(a == 0 && b == 0)) {
56             if (flag == false) {
57                 continue;
58             }
59             if (mapping.find(a) == mapping.end()) {
60                 mapping[a] = p++;
61             }
62             if (mapping.find(b) == mapping.end()) {
63                 mapping[b] = p++;
64             }
65             if (cntD[mapping[b]] == 1) {
66                 flag = false;
67                 continue;
68             }
69             cntD[mapping[b]]++;
70             cnt++;
71         }
72         flag = flag && isTree(p);
73         if (flag) {
74             printf("Case %d is a tree.\n", caseCnt);
75         }
76         else {
77             printf("Case %d is not a tree.\n", caseCnt);
78         }
79
80     }
81     return 0;
82 }

提交答案错误。

这里存在一种特殊情况

比如输入 2 1 3 4 4 5 5 3 0 0

即 2->1  3->4->5->3

成环时也满足只有一个入度为0,其余入度均为1

因此还需要去判断是否成环,有点麻烦,不想做了

时间: 2024-12-21 12:37:13

九度oj 题目1481:Is It A Tree?的相关文章

九度oj 题目1007:奥运排序问题

九度oj 题目1007:奥运排序问题   恢复 题目描述: 按要求,给国家进行排名. 输入:                        有多组数据. 第一行给出国家数N,要求排名的国家数M,国家号从0到N-1. 第二行开始的N行给定国家或地区的奥运金牌数,奖牌数,人口数(百万). 接下来一行给出M个国家号. 输出:                        排序有4种方式: 金牌总数 奖牌总数 金牌人口比例 奖牌人口比例 对每个国家给出最佳排名排名方式 和 最终排名 格式为: 排名:排名

九度oj 题目1546:迷宫问题 (概率dp guess消元)

题目链接:点击打开链接 题目描述: 给定一个n*m的迷宫,如 S.. ..# E.E 其中,S代表开始位置,#代表不可行走的墙,E代表出口. 主人公从开始位置出发,每次等概率的随机选择下一个可以行走的位置,直到到达某一个出口为止. 现在他想知道,在这一概率事件中,它从开始位置走到某一个出口的期望步数是多少. 输入: 输入包含多组测试用例,每组测试用例由两个整数n,m(1<=n,m<=15)开始,代表迷宫的大小 接下去n行每行m个字符描述迷宫信息,具体规则如题面所述. 数据保证至少存在一个E和一

九度oj题目1009:二叉搜索树

题目描述: 判断两序列是否为同一二叉搜索树序列 输入:                        开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接下去一行是一个序列,序列长度小于10,包含(0~9)的数字,没有重复数字,根据这个序列可以构造出一颗二叉搜索树. 接下去的n行有n个序列,每个序列格式跟第一个序列一样,请判断这两个序列是否能组成同一颗二叉搜索树. 输出:                        如果序列相同则输出YES,否则输出NO 样

九度oj 题目1171:C翻转

题目描述: 首先输入一个5 * 5的数组,然后输入一行,这一行有四个数,前两个代表操作类型,后两个数x y代表需操作数据为以x y为左上角的那几个数据. 操作类型有四种:  1 2 表示:90度,顺时针,翻转4个数  1 3 表示:90度,顺时针,翻转9个数  2 2 表示:90度,逆时针,翻转4个数  2 3 表示:90度,逆时针,翻转9个数 输入: 输入有多组数据. 每组输入一个5 * 5的数组,然后输入一行,这一行有四个数,前两个代表操作类型,后两个数x y代表需操作数据为以x y为左上角

九度OJ—题目1032:ZOJ

题目描述: 读入一个字符串,字符串中包含ZOJ三个字符,个数不一定相等,按ZOJ的顺序输出,当某个字符用完时,剩下的仍然按照ZOJ的顺序输出. 输入: 题目包含多组用例,每组用例占一行,包含ZOJ三个字符,当输入"E"时表示输入结束. 1<=length<=100. 输出: 对于每组输入,请输出一行,表示按照要求处理后的字符串. 具体可见样例. 样例输入: ZZOOOJJJ ZZZZOOOOOJJJ ZOOOJJ E 样例输出: ZOJZOJOJ ZOJZOJZOJZOO

九度oj 题目1552:座位问题

题目描述: 计算机学院的男生和女生共n个人要坐成一排玩游戏,因为计算机的女生都非常害羞,男生又很主动,所以活动的组织者要求在任何时候,一个女生的左边或者右边至少有一个女生,即每个女生均不会只与男生相邻.现在活动的组织者想知道,共有多少种可选的座位方案. 例如当n为4时,共有 女女女女, 女女女男, 男女女女, 女女男男, 男女女男, 男男女女, 男男男男7种. 输入: 输入包含多组测试用例,每组测试用例仅包含一个整数n(1<=n<=1000). 输出: 对于每组测试用例,输出一个数代表可选的方

九度oj 题目1499:项目安排

题目描述: 小明每天都在开源社区上做项目,假设每天他都有很多项目可以选,其中每个项目都有一个开始时间和截止时间,假设做完每个项目后,拿到报酬都是不同的.由于小明马上就要硕士毕业了,面临着买房.买车.给女友买各种包包的鸭梨,但是他的钱包却空空如也,他需要足够的money来充实钱包.万能的网友麻烦你来帮帮小明,如何在最短时间内安排自己手中的项目才能保证赚钱最多(注意:做项目的时候,项目不能并行,即两个项目之间不能有时间重叠,但是一个项目刚结束,就可以立即做另一个项目,即项目起止时间点可以重叠). 输

九度oj 题目1014:排名

题目1014:排名 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:9361 解决:2820 题目描述:     今天的上机考试虽然有实时的Ranklist,但上面的排名只是根据完成的题数排序,没有考虑每题的分值,所以并不是最后的排名.给定录取分数线,请你写程序找出最后通过分数线的考生,并将他们的成绩按降序打印. 输入: 测试输入包含若干场考试的信息.每场考试信息的第1行给出考生人数N ( 0 < N < 1000 ).考题数M ( 0 < M < = 10 ).分数线(

九度oj 题目1050:完数

题目1050:完数 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8778 解决:3612 题目描述: 求1-n内的完数,所谓的完数是这样的数,它的所有因子相加等于它自身,比如6有3个因子1,2,3,1+2+3=6,那么6是完数.即完数是等于其所有因子相加和的数. 输入: 测试数据有多组,输入n,n数据范围不大. 输出: 对于每组输入,请输出1-n内所有的完数.如有案例输出有多个数字,用空格隔开,输出最后不要有多余的空格. 样例输入: 6 样例输出: 6 1 #include <io