A graph which is connected and acyclic can be considered a tree. The height of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root.

翻译:一个连通的无环图可以看作是一棵树。树的高度取决于选定的根。现在你应该找到一棵最高的树的根。这样的根叫做最深根。

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤104​​ ) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N−1 lines follow, each describes an edge by given the two adjacent nodes’ numbers.

翻译:每个输入文件包含一个测试用例。对于每种情况,第一行包含一个正整数N(≤104),这是节点的数目,因此节点编号从1到N。然后N−1行,每行通过给定两个相邻节点的编号来描述一条边。

Output Specification:

For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print Error: K components where K is the number of connected components in the graph.

翻译:对于每个测试用例,将每个最深的根打印在一行中。如果这样的根不是唯一的,请按数字的递增顺序打印。如果给定的图不是树,则打印Error: K components,其中K是图中连通块个数。

Sample Input 1:

5
1 2
1 3
1 4
2 5

Sample Output 1:

3
4
5

Sample Input 2:

5
1 3
1 4
2 5
3 4

Sample Output 2:

Error: 2 components

思路

刚开始看到要求连通块数和树的高度,第一反应就是用DFS求解。这里确实也是用DFS,求出了图中最高的树的高度和连通块树,但接下来在如何用递归来记录当高度和最高高度一样时的根结点上犯了难…思考了很久发现自己陷入了思维定势,我总感觉根是1。但其实题目已经暗示我们了树的高度取决于选定的根,也就是说这棵树在不停的变化根结点,然后根据当前的根结点求高度,比如样例1:

    1                             3                   4/ | \   __以3为根变成这样____    |  __以4为根__      |2  3  4                          1                   1\                              / \                 / \5                            2   4               2   3|                   |5                   5

这样想的话就可以直接用BFS求层数的方法,当某个点为根时,直接求它的高度就行了!
于是我的思路就变成了,利用DFS求出最高的高度以及连通块数,再使用BFS对每个点,求它作为根结点时的高度。当高度等于最高高度时,加入vector容器,最后让容器内元素排序输出。但是我写的代码测试点3超时,测试点5错误,只拿了22分,代码如下

22分做法

#include <iostream>
#include <cstdlib>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
vector<int> G[10002];
map<int, bool> visit; //visit用来记录结点访问情况
map<int, bool> visit2; //visit2用来判断连通块个数
int block = 0, max_height = 0, n;
void dfs_trav();
void dfs(int, int);
int get_height(int);
int main()
{cin >> n;for (int i = 0; i < n - 1; i++){int node1, node2;cin >> node1 >> node2;G[node1].push_back(node2);G[node2].push_back(node1);}dfs_trav();if (block > 1)cout << "Error: " << block << " components";else{vector<int> vec;//一个一个判断是否等于最高高度for (int i = 1; i <= n; i++)if (get_height(i) == max_height)vec.push_back(i);sort(vec.begin(), vec.end()); //排序for (int i = 0; i < vec.size(); i++)cout << vec[i] << endl;}system("pause");return 0;
}
void dfs_trav()
{for (int i = 1; i <= n; i++){visit.clear();if (visit2[i] == false)block++; //记录连通块数dfs(i, 1);}
}
void dfs(int v, int h)
{if (h > max_height)max_height = h;visit[v] = true;visit2[v] = true;for (int i = 0; i < G[v].size(); i++)if (visit[G[v][i]] == false)dfs(G[v][i], h + 1);
}
int get_height(int v)
{//利用队列实现层序遍历int level = 0;map<int, bool> vis;queue<int> que;que.push(v);vis[v] = true;while (!que.empty()){level++;for (int i = 0; i < que.size(); i++){int top = que.front();for (int j = 0; j < G[top].size(); j++){//这里一定要判断是否访问过,因为是无向图//如果不加以判断,比如样例1,结点1时将2加入队列,后面结点2时又会将1加入队列if (vis[G[top][j]] == false)que.push(G[top][j]);vis[G[top][j]] = true;}que.pop();}}return level;
}

ps:写这段代码也让我发现我对DFS理解不够深入,以及层序遍历编写不够熟练(编的时候网上搜了不少次)建议多加练习。
后来想通了如何用递归来记录当高度和最高高度一样时的根结点。定义一个数组用来记录每个结点的深度,然后重新写一个dfs,每次记录一个结点的最高高度。这个做法阴差阳错的解决了测试点5(但目前还是不知道为什么22分做法测试点5会错),现在只剩超时的测试点3了。

23分做法

#include <iostream>
#include <cstdlib>
#include <vector>
#include <map>
using namespace std;
vector<int> G[10002];
int depth[10001];
map<int, bool> visit;
map<int, bool> visit2;
int block = 0, max_height = 0, n;
void dfs_trav();
void dfs(int, int);
void dfs_getheight(int, int&, int); //用来求高度
int main()
{cin >> n;for (int i = 0; i < n - 1; i++){int node1, node2;cin >> node1 >> node2;G[node1].push_back(node2);G[node2].push_back(node1);}dfs_trav();if (block > 1)cout << "Error: " << block << " components";else{for (int i = 1; i <= n; i++){int d = 0, h = 1;visit.clear();dfs_getheight(i, d, h);depth[i] = d;}for (int i = 1; i <= n; i++)if (depth[i] == max_height)cout << i << endl;}system("pause");return 0;
}
void dfs_trav()
{for (int i = 1; i <= n; i++){visit.clear();if (visit2[i] == false)block++; //记录连通块数dfs(i, 1);}
}
void dfs(int v, int h)
{if (h > max_height)max_height = h;visit[v] = true;visit2[v] = true;for (int i = 0; i < G[v].size(); i++)if (visit[G[v][i]] == false)dfs(G[v][i], h + 1);
}
void dfs_getheight(int v, int& depth, int h)
{if (h > depth)depth = h; //depth用来记录该结点v的最高高度,必须是引用类型visit[v] = true;for (int i = 0; i < G[v].size(); i++)if (visit[G[v][i]] == false)dfs_getheight(G[v][i], depth, h + 1);
}

优化思路

PAT甲级1021 Deepest Root//未满分相关推荐

  1. PAT甲级1021 Deepest Root :[C++题解]树的最大深度、并查集、dfs求树的深度

    文章目录 题目分析 题目链接 题目分析 分析: 考察知识点:并查集.dfs.树的深度 给定n个结点,n-1条边,只要能保证只有1个连通分量,就是一棵树.否则的话就不是树,它是不连通的. 用并查集来看是 ...

  2. PAT甲级-1021 Deepest Root(25分)

    题目:1021 Deepest Root(25分) 分析:找出以某个节点为根时,最深的根,这题可能会超时要用vector来表示二维数组 疑问:代码一是第二次写的超时了,代码二是第一次写的AC了,找不出 ...

  3. 浙大PAT 1021. Deepest Root (25)

    1021. Deepest Root (25) 时间限制 1500 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue A graph ...

  4. 1021. Deepest Root (25)

    题目链接:http://www.patest.cn/contests/pat-a-practise/1021 题目: 1021. Deepest Root (25) 时间限制 1500 ms 内存限制 ...

  5. 【PAT - 甲级1021】Deepest Root (25分)(并查集,暴力枚举)

    题干: A graph which is connected and acyclic can be considered a tree. The height of the tree depends ...

  6. 【分析】1021 Deepest Root (25 分)【DFS解法】

    立志用最少的代码做最高效的表达 PAT甲级最优题解-->传送门 A graph which is connected and acyclic can be considered a tree. ...

  7. 浙大PAT甲级-1021

    还是看了凌大佬的博客才全部ac的 (https://blog.csdn.net/iaccepted/article/details/20454519) #include <iostream> ...

  8. 【PAT甲级】1021 Deepest Root (25 分)(暴力,DFS)

    题意: 输入一个正整数N(N<=10000),然后输入N-1条边,求使得这棵树深度最大的根节点,递增序输出.如果不是一棵树,输出这张图有几个部分. trick: 时间比较充裕数据可能也不是很极限 ...

  9. 1021 Deepest Root

    要解决两大问题: 1. 数包含几个连通分量 2. 如何找到最深结点 注意:connected components的意思是连通分量 问题1我用并查集解决 问题2转化为如何得到每个结点的深度 值得注意之 ...

  10. 1021 Deepest Root (25 分) 【难度: 中 / 知识点: 树的直径 连通块】

    https://pintia.cn/problem-sets/994805342720868352/problems/994805482919673856 方法一: 数组模拟邻接表 第一步: 爆搜df ...

最新文章

  1. hacktoberfest_Hacktoberfest 2018:如何获得免费衬衫—即使您是编码新手
  2. 深入理解Java Proxy和CGLIB动态代理原理
  3. 【图像分割应用】设备自动化(一)——自动驾驶
  4. 用计算机图形学画字母,r 语言快速出图——单因素方差带字母显著性标记
  5. 设计模式3:装饰模式
  6. php实现关键字搜索mysql数据_PHP实现多个关键词搜索查询功能示例
  7. hadoop学习笔记(四):hdfs常用命令
  8. 每天一道剑指offer-链表中第k个节点
  9. html盒子颜色代码,css盒子(示例代码)
  10. Minecraft HMCL 第三方启动器使用教程
  11. Android JNI的调用过程
  12. clickhouse ARRAY JOIN函数
  13. 未转变者服务器保存红字警告,未转变者3.0怎么设置自己开的服
  14. QT开发之老板无法拒绝的辞职信
  15. 如何监控前端页面FPS
  16. 两个路由器+两个主机:简单的网络配置
  17. vue 仿外卖app-数据mock部分
  18. Web前端和后端之区分
  19. tensorflow安装过程-(windows环境下)---详解
  20. MySql函数 - FIND_IN_SET函数

热门文章

  1. 不是会员不让复制粘贴?看我“三板斧”!
  2. POJ - 2142 扩展欧几里得
  3. Contest1389 - 2018年第三阶段个人训练赛第四场. Transit Tree Path(DFS)
  4. python3*1**3 表达式输出结果为_表达式[1, 2, 3]*3的执行结果为______________________。...
  5. 利用C 语言求一元二次方程解
  6. 牛客java选择题每日打卡Day9
  7. PyCharm设置背景颜色为白色
  8. Mac教程——怎么升级系统版本
  9. ios动态效果实现翻页_iOS动画--翻页动画
  10. 单个正态总体方差的置信区间