• 【PAT甲级】1021 Deepest Root


    ✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
    📚专栏地址:PAT题解集合
    📝原题地址:题目详情 - 1021 Deepest Root (pintia.cn)
    🔑中文翻译:最深的根
    📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
    ❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

    1021 Deepest Root

    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.

    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
    
    题意

    第一行包含整数 N N N ,表示节点数量。

    节点编号为 1 ∼ N 1∼N 1N

    接下来 N − 1 N−1 N1 行,每行包含两个整数,表示两个节点之间存在一条边。

    输出最深的根的节点编号。

    如果最深的根不唯一,则按照从小到大的顺序,将它们依次输出,每个占一行。

    如果给定的图不是树,输出 Error: K components ,其中 K K K 是图中连通分量的数量。

    思路
    1. 在输入每条边的信息时,我们可以利用并查集来对该图进行判断,输入前令 k = n ,每输入一条边时就判断这条边两个端点是否已经在同一个连通块中,如果不在则将 k - 1 ,最终的 k 值就是该图连通块的数量。
    2. 如果 k > 1 则该图不是树,输出 Error: K components ,否则对每个结点都进行一次 dfs 操作,找到最深的结点。注意,我们这里的结点是从小到大进行 dfs ,所以最终得到的结果一定是单调递增的,不用再进行排序。
    3. dfs 的过程中,注意不能回溯即当前结点再访问其父结点,需要额外进行判断。
    代码
    #include
    using namespace std;
    
    const int N = 10010, M = 2 * N;
    int h[N], e[M], ne[M], idx;
    int p[N];
    int n;
    
    //链式前向星保存每一条边
    void add(int a, int b)
    {
        e[idx] = b, ne[idx] = h[a], h[a] = idx++;
    }
    
    //并查集查找操作
    int find(int x)
    {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }
    
    //获取当前最大深度,其中u表示当前结点,father表示父结点
    int dfs(int u, int father)
    {
        int depth = 0;
        //遍历其所有孩子结点
        for (int i = h[u]; ~i; i = ne[i])
        {
            int j = e[i];
            if (j == father)   continue;   //防止回溯
            depth = max(depth, dfs(j, u) + 1);
        }
        return depth;
    }
    
    int main()
    {
        //初始化
        cin >> n;
        memset(h, -1, sizeof h);
        for (int i = 1; i <= n; i++)   p[i] = i;
    
        //输入所有边,且用并查集判断该图是否为树
        int k = n;
        for (int i = 0; i < n - 1; i++)
        {
            int a, b;
            cin >> a >> b;
            add(a, b), add(b, a);
            if (find(a) != find(b))
            {
                k--;
                p[find(a)] = find(b);
            }
        }
    
        if (k > 1) printf("Error: %d components\n", k);
        else
        {
            vector<int> nodes;
            int max_depth = 0;
            for (int i = 1; i <= n; i++)
            {
                int depth = dfs(i, 0); //获得当前深度
                if (depth > max_depth) //如果当前深度大于当前最大深度
                {
                    nodes.clear();
                    max_depth = depth;
                    nodes.push_back(i);
                }
                else if (depth == max_depth)   //如果当前深度等于当前最大深度
                    nodes.push_back(i);
            }
    
            //输出结果
            for (auto& x : nodes)  cout << x << endl;
        }
    
        return 0;
    }
    
  • 相关阅读:
    leetcode669. 修剪二叉搜索树(java)
    隆重推出 Incredibuild 10
    速盾网络:CDN用几天关了可以吗?安全吗?
    系统架构设计师 2023年 论文
    基于SSM的校园自助洗衣系统的设计与实现
    Android14之java层:增加系统API(二百二十)
    linux三剑客~sed命令的使用
    正则系列之正则表达式可选参数
    日报系统:优化能源行业管理与决策的利器
    c++ operator overloading
  • 原文地址:https://blog.csdn.net/Newin2020/article/details/127041140