• PTA (Advanced Level) 1021 Deepest Root


    Deepest Root

      A graph which is connected and acyclic can be considered a tree. The hight 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 (10​^4​​) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N1 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条边连接的两个结点。要求判断该无向图是否是一颗树,若是一棵树,由小到大输出以其为根结点时深度最大的点,若不是树则输出连通块数量。

      在解题之前首先看一下题目的限制

      时间限制: 2000 ms
      内存限制: 64 MB
      

      本题结点数量最多1e4个若用二维数组存储邻接矩阵,虽然数组没有超限但是当节点数取到最大1e4个结点时,需要的内存空间超过382MB,所以在这里使用邻接表来存储无向图。对于判断无向图是否为树,由于无向图有n个结点n-1条边,那么只要这个图是连通图,它便肯定是一颗树。我们只需要维护一个并查集便可以达到判断数与输出连通块数量,由于本题时间限制非常松,时间宽松使人暴力,所以在寻找深度最大的根结点时,这里以所有点为根结点暴力深搜获取深度,用set保存所有深度最大的点,之后将其输出即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAX =1e4 + 10;
     4 vector<int> G[MAX];
     5 int f[MAX];
     6 int n;
     7 void init(){    //初始化并查集
     8     for(int i = 1; i <= n; i++)
     9         f[i] = i;
    10 }
    11 int getF(int x) //并查集找爹函数
    12 {
    13     if(f[x] == x)
    14         return x;
    15     else
    16         return f[x] = getF(f[x]);
    17 }
    18 int maxH = 0;
    19 void DFS_getH(int u, int height, int preNode){  //深搜获取深度
    20     maxH = max(maxH, height);
    21     for(int i = 0; i < G[u].size(); i++)
    22         if(G[u][i] != preNode)
    23             DFS_getH(G[u][i], height + 1, u);
    24 }
    25 int main(){
    26     scanf("%d", &n);    //输入结点数量
    27     init(); //初始化并查集
    28     memset(G, 0, sizeof(G));
    29     for(int i = 0; i < n - 1; i++){ //输入n-1条边
    30         int u, v;
    31         scanf("%d%d", &u, &v);
    32         G[u].push_back(v);
    33         G[v].push_back(u);
    34         int fu = getF(u);
    35         int fv = getF(v);
    36         if(fu != fv)    //合并一条的两个端点
    37             f[fu] = fv;
    38     }
    39     int cnt = 0;    //记录连通块个数
    40     for(int i = 1; i <= n; i++){    //获取连通块个数
    41         if(f[i] == i)
    42             cnt++;
    43     };
    44     if(cnt != 1)    //若连通块个数不等于1证明给出的图不是一颗树
    45         printf("Error: %d components
    ", cnt);   //输出连通块个数
    46     else{
    47         set<int> ans;
    48         int ansH = 0;
    49         for(int i = 1; i <= n; i++){
    50             maxH = 0;
    51             DFS_getH(i, 1, 0);  //获取每一个点为根时对应的树高(用maxH记录)
    52             if(maxH > ansH){    //ansH记录当前最高深度
    53                 ansH = maxH;    //若找到深度更大的点便清空集合重新记录
    54                 ans.clear();
    55                 ans.insert(i);
    56             }else if(maxH == ansH){ //找到深度与当前最大深度相同的点便加入集合
    57                 ans.insert(i);
    58             }
    59         }
    60         for(auto i : ans){
    61             printf("%d
    ", i);
    62         }
    63     }
    64     return 0;
    65 }
  • 相关阅读:
    Jmeter生成HTML报告
    Python多线程(生成动态参数)
    小程序利用canvas生成图片加文字,保存到相册
    小程序商城数量加减效果
    支付宝小程序tab切换滑动
    数据排序,从小到大,从大到小,ajax
    小程序上拉加载更多,onReachBottom
    小程序tab导航切换样式
    小程序动画Animation,高度增加动画形式,图标旋转动画形式
    iview weapp icon组件自定义图标 小程序
  • 原文地址:https://www.cnblogs.com/suvvm/p/10319911.html
Copyright © 2020-2023  润新知