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

  • 相关阅读:
    Linq增删查改
    AspNetPager 分页显示
    简单C#数据库操作类
    SQL重复记录处理(查找,过滤,删除)
    Asp.Net配置Web.config连接数据库SqlServer
    转:Asp.Net网站项目发布到IIS后验证码不能显示的问题解决
    将一行含有日期范围的数据按照单日日期拆分
    asp.net过滤HTML标签的几个函数
    循环批量更新的的存储过程(属于转载)
    CheckBox的CheckedChanged事件获取所在GridView中的Cell值
  • 原文地址:https://www.cnblogs.com/liumengliang/p/12764090.html
Copyright © 2011-2022 走看看