树的直径
Posted liumengliang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树的直径相关的知识,希望对你有一定的参考价值。
一、概念
在一棵树中找到距离根节点最远的两个点,这两个点之间的距离为树的直径
二、算法
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
以上是关于树的直径的主要内容,如果未能解决你的问题,请参考以下文章