求樹的直徑算法
標簽: 圖論——樹的直徑
閱讀體驗:https://zybuluo.com/Junlier/note/1251025
樹的直徑
樹的直徑是樹上的最長路
求法:2遍\(Dfs(Bfs)\)
沒錯,真的這么簡單......
- 先隨便找個點i開始\(Dfs\),然后找到一條最長路徑(假設終點是\(u\))
- 然后從u開始再一次\(Dfs\),再找到一條最長路徑(假設終點是\(v\)),\((u,v)\)就是樹的直徑了......
PS:樹的直徑可以有多條(想想定義就知道)
證明:為什么呢?
假設樹的直徑是\((u,v)\),第一次\(Dfs\)找到\((i,j)\)
如果我們\(Dfs\)找到了樹的直徑的一端\((u/v)\),那么第二次就一定可以找到樹的直徑對吧
那么證明轉化成了第一次\(Dfs\)是否找到了樹的直徑的一端\((u/v)\)
PS:建議自己手動畫棵樹來一邊看着證明 效果更佳
首先假設i在最長路徑上:
- 反證法:
- 如果找到的
(i,j)
不是(i,u)
,那么(i,j)
一定可以和(i,v)
拼成另一條更長路(j,v)
(因為(i,j)>=(i,u)
而等於正印證了上面講到的多條直徑),所以與假設(u,v)
是最長路不符,那么猜想的方法成立
如果i不在最長路上呢?
- 首先\(i\)肯定可以和最長路上的一個點\(k\)(從\(i\)到最長路最先遇到的點)連通對吧
- 我們假設\(u\)是最長路距離\(k\)較遠的一個末端,那么從\(i\)找出去的最長路一定會到\(u\)
- 證明:如果
(i,j)
不是(i,u)
(即(i,j)>(i,u)
),那么(i,j)+(i,k)>(j,u)
,即我們找到了另一條(j,k)>(j,u)
,那么說明我們假設的直徑(u,v)
又可以被更長的(k,v)
更新,假設不成立,那么猜想成立,證明完畢
總結一下
綜上所述,兩遍\(Dfs(Bfs)\)可以找到樹的直徑
而樹的直徑在很多圖論題里面是很有用的,這種方法就保證了我們的時間復雜度O(n)
為我們其他計算提供了更優的復雜度空間。。。
\(yep\)
推薦題目
P2491 [SDOI2011]消防(有難度的啊)(只放了洛谷的地址,各大\(OJ\)應該都有)