zoukankan      html  css  js  c++  java
  • 树的直径

    一、概念

      在一棵树中找到距离根节点最远的两个点,这两个点之间的距离为树的直径

    二、算法

      1.求法:求树的直径的方法就是在树上任选一点u,求距离点u最远的点y,再求距离点y最远的点s,点y到点s的距离即为树的直径。

      2.证明:假设此树的最长路径是从s到t,我们选择的点为u。反证法:假设搜到的点是v。

        1、v在这条最长路径上,那么dis[u,v]>dis[u,v]+dis[v,s],显然矛盾。
        2、v不在这条最长路径上,我们在最长路径上选择一个点为po,则dis[u,v]>dis[u,po]+dis[po,t],那么有dis[s,v]=dis[s,po]+dis[po,u]+dis[u,v]>dis[s,po]+dis[po,t]=dis[s,t],即dis[s,v]>dis[s,t],矛盾。
        也许你想说u本身就在最长路径,或则其它的一些情况,但其实都能用类似于上面的反证法来证明的。
        综上所述,你两次dfs(bfs)就可以求出最长路径的两个端点和路径长度。
    (注:该证明引自原文链接:https://blog.csdn.net/qianguch/java/article/details/78216860)

    对于每个节点我们要记录两个值:

    f1 [ i ] 表示以 i 为根的子树中,i 到叶子结点距离的最大值

    f2 [ i ] 表示以 i 为根的子树中,i 到叶子结点距离的次大值

    对于一个节点,它到叶子结点距离的最大值和次大致所经过的路径肯定是不一样的

    若j是i的儿子,那么(下面的 w [ i ][ j ] 表示 i 到 j 的路径长度):

    若 f1 [ i ] < f1 [ j ] + w [ i ][ j ],f2 [ i ] = f1 [ i ],f1 [ i ] = f1 [ j ] + w [ i ][ j ];
    否则,若 f2 [ i ] < f1 [ j ] + w [ i ][ j ],f2 [ i ] = f1 [ j ] + w [ i ][ j ]; 
    理解:这样做就是,先看能否更新最大值,若能,它的次大值就是原先的最大值,再更新它的最大值;若不能,就看能不能更新次大值,若能,就更新,不能就不管它

    这样的话,最后的答案 answer = max { f1 [ i ] + f2 [ i ] }
    引自:https://blog.csdn.net/forever_dreams/java/article/details/81051578

  • 相关阅读:
    一文详解云上自动化部署集群管理工具 Nebula Operator
    手把手教你从数据预处理开始体验图数据库
    图查询语言的历史回顾短文
    集群通信:从心跳说起
    @Constraint 自定义注解校验手机号
    【工具】maven插件自动生成mapper文件
    【工具】方法日志打印+任务切片
    简单梳理下 Vue3 的新特性
    团队与领导力健康检查 | 体检表
    详细介绍Scrum Master八大职责(Scrum Master能力说明)
  • 原文地址:https://www.cnblogs.com/liumengliang/p/12764090.html
Copyright © 2011-2022 走看看