• PAT甲级1021Deepest Root


    题目链接

    https://pintia.cn/problem-sets/994805342720868352/problems/994805482919673856

    题解

    题目要求

    • 输入
      • N:正整数,不超过10000,结点的数量,索引为[1,N]
      • N-1条边
    • 输出
      • 输出深度最大的根结点,如果不唯一,则按升序输出。如果这个图不是树,则输出图中连通分量的数量

    方法一

    解题思路

    • 没有回路的无向图是连通的当且仅当它是树
    1. 求该图的连通分量数,如果连通分量数大于1,则输出连通分量数,程序终止;
    2. 对于每一个结点,将其作为根结点,通过dfs求其高度depth,将depth与全局最大高度maxDepth比较,并更新全局最大高度及其对应根结点;
    3. 输出根结点

    代码

    如果用邻接矩阵,则第3个点会超时,用邻接表则不超时。

    // Problem: PAT Advanced 1021
    // URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805482919673856
    // Tags: 树 图 连通分量 连通图 DFS
    
    #include <iostream>
    #include <vector>
    using namespace std;
    
    const int MAXN = 10001;
    int n, tempDepth = 0, depth = 0, maxDepth = 0;
    vector<int> deepestRoot;
    vector<vector<int>> v;
    bool visited[MAXN];
    
    void dfs(int u){
        visited[u] = true;
        tempDepth += 1;
    
        if (depth < tempDepth){
            depth = tempDepth;
        }
        for(int i = 0; i < v[u].size(); i++){
            if (!visited[v[u][i]]){
                dfs(v[u][i]);
            }
        }
    
        tempDepth -= 1;
    }
    
    int main()
    {
        scanf("%d", &n);
        v.resize(n+1);
        int v1, v2;
        for (int i = 0; i < n - 1; i++){
            scanf("%d %d", &v1, &v2);
            v[v1].push_back(v2);
            v[v2].push_back(v1);
        }
    
        int num = 0;
        for (int i = 1; i <= n; i++){
            if (!visited[i]){
                dfs(i);
                num++;
            }
        }
        if (num > 1){
            printf("Error: %d components", num);
            return 0;
        }
        else if (num == 1){
            for (int root = 1; root <= n; root++){
                fill(visited + 1, visited + 1 + n, false);
                depth = 0;
                dfs(root);
                if (maxDepth < depth){
                    maxDepth = depth;
                    deepestRoot.clear();
                    deepestRoot.push_back(root);
                }
                else if (maxDepth == depth){
                    deepestRoot.push_back(root);
                }
            }
    
            for (int i = 0; i < deepestRoot.size(); i++){
                printf("%d
    ", deepestRoot[i]);
            }
        }
        
        return 0;
    }
    

    方法二

    思路

    1. 第一次DFS:判断连通分量数量,如果超过1,则直接输出,程序结束

      同时保存深度最大的那些结点到数组s中

    2. 第二次DFS:从s中的任一个结点出发进行DFS,此时深度最大的结点与s的并集就是结果

    这个思路很妙,并且速度很快:这是无向图,是双向的,所以正序倒序各求一遍合起来就是结果。

    代码

    // Problem: PAT Advanced 1021
    // URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805482919673856
    // Tags: 树 图 连通分量 连通图 DFS set
    
    #include <iostream>
    #include <vector>
    #include <set>
    using namespace std;
    
    const int MAXN = 10001;
    int n, depth = 0, maxDepth = 0;
    vector<int> temp;
    set<int> result;
    vector<vector<int>> v;
    bool visited[MAXN];
    
    void dfs(int u){
        visited[u] = true;
        depth += 1;
    
        if (maxDepth < depth){
            maxDepth = depth;
            temp.clear();
            temp.push_back(u);
        }
        else if (maxDepth == depth){
            temp.push_back(u);
        }
        for(int i = 0; i < v[u].size(); i++){
            if (!visited[v[u][i]]){
                dfs(v[u][i]);
            }
        }
    
        depth -= 1;
    }
    
    int main()
    {
        scanf("%d", &n);
        v.resize(n+1);
        int v1, v2;
        for (int i = 0; i < n - 1; i++){
            scanf("%d %d", &v1, &v2);
            v[v1].push_back(v2);
            v[v2].push_back(v1);
        }
    
        int num = 0;
        for (int i = 1; i <= n; i++){
            if (!visited[i]){
                dfs(i);
                num++;
            }
        }
    
        if (num > 1){
            printf("Error: %d components", num);
            return 0;
        }
        else if (num == 1){
            for (int i = 0; i < temp.size(); i++)
                result.insert(temp[i]);
            
            fill(visited + 1, visited + 1 + n, false);
            int u = temp[0];
            temp.clear();
            dfs(u);
            for (int i = 0; i < temp.size(); i++)
                result.insert(temp[i]);
            for (auto it = result.begin(); it != result.end(); it++)
                printf("%d
    ", *it);
        }
    
        return 0;
    }
    

    参考链接

    https://blog.csdn.net/liuchuo/article/details/52294178


    作者:@臭咸鱼

    转载请注明出处:https://www.cnblogs.com/chouxianyu/

    欢迎讨论和交流!


  • 相关阅读:
    spring boot 报错 Failed to read HTTP message
    spring boot 之 Mybatis 配置
    Java生成xlsx格式的excel文件
    遍历FTP目录及下载
    Spring 报错
    git ssh key生成
    spring mvc原理
    LightOJ 1154
    Light OJ 1153
    入栈出栈的顺序问题
  • 原文地址:https://www.cnblogs.com/chouxianyu/p/13730946.html
Copyright © 2020-2023  润新知