树的直径
树的直径
树的直径有两种求法,一种是两次dfs,一种是树形dp
两次dfs
从任意一点跑dfs找到最远点,这个点是直径的一段,再从这个点dfs到最远端,也就是直径的另外一端
这个oiwiki上讲的很细,但我更喜欢他的证明
证明
使用反证法。记出发节点为 $y$。设真实的直径是 $\delta(s,t)$,而从 $y$ 进行的第一次 DFS 到达的距离其最远的节点 $z$ 不为 $t$ 或 $s$。共分三种情况:
- 若 $y$ 在 $\delta(s,t)$ 上:
有 $\delta(y,z) > \delta(y,t) \Longrightarrow \delta(x,z) > \delta(x,t) \Longrightarrow \delta(s,z) > \delta(s,t)$,与 $\delta(s,t)$ 为树上任意两节点之间最长的简单路径矛盾。
- 若 $y$ 不在 $\delta(s,t)$ 上,且 $\delta(y,z)$ 与 $\delta(s,t)$ 存在重合路径:
有 $\delta(y,z) > \delta(y,t) \Longrightarrow \delta(x,z) > \delta(x,t) \Longrightarrow \delta(s,z) > \delta(s,t)$,与 $\delta(s,t)$ 为树上任意两节点之间最长的简单路径矛盾。
- 若 $y$ 不在 $\delta(s,t)$ 上,且 $\delta(y,z)$ 与 $\delta(s,t)$ 不存在重合路径:
有 $\delta(y,z) > \delta(y,t) \Longrightarrow \delta(x’,z) > \delta(x’,t) \Longrightarrow \delta(x,z) > \delta(x,t) \Longrightarrow \delta(s,z) > \delta(s,t)$,与 $\delta(s,t)$ 为树上任意两节点之间最长的简单路径矛盾。
综上,三种情况下假设均会产生矛盾,故原定理得证。
注意
上述证明过程建立在所有路径均不为负的前提下。如果树上存在负权边,则上述证明不成立。故若存在负权边,则无法使用两次 DFS 的方式求解直径
树形dp
在一个子树中,其直径即为包含子树根的最长链与次长链拼接而成
我们记录当 $1$ 为树的根时,每个节点作为子树的根向下,所能延伸的最长路径长度 $d_1$ 与次长路径(与最长路径无公共边)长度 $d_2$,那么直径就是对于每一个点,该点 $d_1 + d_2$ 能取到的值中的最大值。
$d$数组记子树最长链
实现
1 |
|