zoukankan      html  css  js  c++  java
  • PAT1021 Deepest Root

    题目地址:here

    题目大意:无环连通图也可以视为一棵树,选定图中任意一点作为根,如果这时候整个树的深度最大,该点称为 deepest root。 给定一个图,按升序输出所有 deepest root。如果给定的图有多个连通分量,则输出连通分量的数量。

    解法:先任选一点A从该点开始dfs,找出距离该点最远的点B,则B是一个deepest root;然后从B点开始dfs,找到距离B最远的所有点,这些点加上B点都是deepest root。对于有多个连通分支的,我们可以通过遍历完所有节点调用dfs函数的次数来判断(当然也可以用并查集来求连通分支数目)。                                                                                本文地址

    主要是解法中前半段的证明,为什么距离A最远的B是deepest root:

    • 一个概念,定义从deepest root到其最远叶子的路径为树的 “最长路径”
    • 两条最长路径一定有个交点,可以用反证法证明:如果没有交点,由于一棵树中,任意两点都是连通的,可以通过对两条路径组合出一条更长的路径,这与两条路径是最长的矛盾。
    • 假设从A点dfs后,最远的点是B, 假设某一个距离A更近的点D也是deepest root,那么以B、D为端点的最长路径一定有一个交点,假设该交点为k,则有两种情况:(1)最长路径为B....k....D,这种情况和假设不矛盾(2)最长路径为B....k.... 和 D....k....,k后面的路径长度相同。由于A到k一定有一条路径,那么各点之间的关系可以是A...K....D, A....K....B  或者K...A....D,  K...A....B 由于len(A...B)>len(A....D),两种情况下都有:len(B....K) > len(D....K),即len(B....K....) > len(D....K....) 这和D....k....是最长路径矛盾

    注意:本题的输入图是默认没有环的

    代码如下:                                                                                                             本文地址

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<vector>
     5 #include<algorithm>
     6 using namespace std;
     7 //本题无向图中默认是没有环的
     8 //先任选一点A从该点开始dfs,找出距离该店最远的点B
     9 //然后从B点dfs,找到距离B最远的所有点,这些点加上B点都是deepest root
    10 
    11 //用邻接表存储图
    12 struct GraphNode
    13 {
    14     vector<int> adja;
    15 };
    16 
    17 bool *visited;
    18 GraphNode *graph;
    19 
    20 //从某个节点开始深度优先遍历图,并求出相应的树的高度,而且保存离树根最远的节点
    21 void dfs(int rootIndex, int level, int &height, vector<int> &farthestNode)
    22 {
    23     visited[rootIndex] = true;
    24     if(height < level)
    25     {
    26         height = level;
    27         farthestNode.clear();
    28         farthestNode.push_back(rootIndex);
    29     }
    30     else if(height == level)
    31         farthestNode.push_back(rootIndex);
    32     for(int i = 0; i < graph[rootIndex].adja.size(); i++)
    33     {
    34         int son = graph[rootIndex].adja[i];
    35         if(visited[son] == false)
    36             dfs(son, level+1, height, farthestNode);
    37     }
    38 }
    39 int main()
    40 {
    41     int N;
    42     scanf("%d", &N);
    43     if(N == 1){printf("1"); return 0;}
    44     graph = new GraphNode[N+1];
    45     visited = new bool[N+1];
    46     for(int i = 1; i <= N-1; i++)
    47     {
    48         int a,b;
    49         scanf("%d%d", &a, &b);
    50         graph[a].adja.push_back(b);
    51         graph[b].adja.push_back(a);
    52     }
    53     vector<int> farthestNode;
    54     int height = 0, components = 0;
    55     memset(visited, 0, sizeof(bool)*(N+1));
    56     //通过dfs遍历整个图来计算图的连通分支,调用dfs的次数就是连通分支数目
    57     for(int i = 1; i <= N; i++)
    58         if(visited[i] == false)
    59         {
    60             visited[i] == true;
    61             dfs(i, 0, height, farthestNode);
    62             components++;
    63         }
    64     if(components > 1)
    65         printf("Error: %d components",components);
    66     else
    67     {
    68         int k = farthestNode[0];
    69         farthestNode.clear();
    70         height = 0;
    71         memset(visited, 0, sizeof(bool)*(N+1));
    72         dfs(k, 0, height, farthestNode);
    73         farthestNode.push_back(k);
    74         sort(farthestNode.begin(), farthestNode.end());
    75         for(int i = 0; i < farthestNode.size(); i++)
    76             printf("%d
    ", farthestNode[i]);
    77     }
    78     return 0;
    79 }

     【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3401764.html

  • 相关阅读:
    c# vs2010 excel 上传oracle数据
    Viola-Jones人脸检測
    apache commons-configuration包读取配置文件
    linux 读取文件
    linux 统计某个文件的行数
    linux 判空处理
    linux 查看某个目录下文件的数量
    nginx 配置文件正确性测试
    使用postman上传excel文件测试导入excel
    java 反射获取字段为List类型中的泛型类型
  • 原文地址:https://www.cnblogs.com/TenosDoIt/p/3401764.html
Copyright © 2011-2022 走看看