PAT甲级真题 1021 Deepest Root (25分) C++实现(两次DFS遍历,注意测试点3内存超限错误,需用邻接表存储图)

题目

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 (<=10000) 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.
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.
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后,判断是否遍历完了(visited数组是否都为true),若没遍历完,则图有多个连通分支,继续从未遍历过的节点DFS,累计连通分支个数,直到把所有节点遍历完为止。

然后找作为根有最大深度的节点。一开始的想法是,分别从所有节点开始DFS遍历,用额外的数组记录每个节点为根时能达到的最大深度,最后输出深度最大的节点们。这个方法虽然也能通过,但比较笨拙,用了n次DFS。

后来参考了柳神的做法,只需两次DFS:将第一次DFS时最深的节点记录到set里,从中任选一个节点再进行一次DFS,得到最深的节点记录到另一个set,两个set的并集即为所求(set内的元素自动递增排序,且不会insert重复元素,十分合适)。

每次DFS前,记得将visited复原:

fill(visited.begin(), visited.end(), false);

核心是DFS的写法,如果不用全局变量保存visited的话,需要传入visited的引用,否则递归函数修改的值将无效。下面是示例代码:

vector<vector<int> > E;  //全局变量
//深度优先遍历,m是当前节点,visited记录访问情况,depth记录当前迭代深度
void DFS(int m, vector<bool> & visited, int depth){
   
    depth++;  //当前迭代层数
    visited[m] = true;  //当前访问节点
    for (int i=0; i<E[m].size(); i++){
     //E是邻接表表示的图
        if (!visited[E[m][i]]){
   
            DFS(E[m][i], visited, depth);
        }
    }
    return;
}
//调用
DFS(1, visited, 0);  //从节点1开始深度遍历

若使用邻接矩阵存储图的话,测试点3会提示内存超限!!! 因为树是稀疏图,所以最好用邻接表存储。

代码

方法一:n次DFS,记录每个节点为根时能达到的最大深度

#include <iostream>
#include <vector>
using namespace std;

vector<vector
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值