AtCoder 🟢 ABC428E Farthest Vertex
🔗 🟢 ABC428E Farthest Vertex
Problem Statement
題目簡述
給定一棵 個頂點的樹,對每個頂點 ,找出距離 最遠的頂點。若有多個同距頂點,輸出編號最大的那個。
Constraints
約束條件
- 輸入的圖是一棵樹
思路:樹的直徑端點性質
關鍵性質:最遠點必為直徑端點
在一棵樹中,對於任意頂點 ,距離 最遠的頂點一定是該樹某條直徑的端點之一。
直覺理解:樹的直徑是最長的路徑,它的兩個端點 代表了樹中「最極端」的兩個位置。任何頂點離得最遠的點,不可能跳出直徑端點所能覆蓋的距離範圍。
證明(反證法)
設 為給定樹的直徑兩端點,因此這棵樹的直徑 。
假設存在某個頂點 ,距離它最遠的頂點 ,即滿足:
且 。
為了嚴格證明矛盾,我們將 和 的路徑映射(投影)到直徑 上。設它們分別在 和 點與直徑相交( 和 為直徑上的頂點,且可能重合)。不失一般性,我們假設 在直徑上的相對順序如下圖:
graph LR
v(("v")) -.-|"d(v, u)"| u(("u"))
w(("w (假想的最遠點)")) -.-|"d(w, z)"| z(("z"))
x(("x (端點)")) ===|"d(x, u)"| u
u ===|"d(u, z)"| z
z ===|"d(z, y)"| y(("y (端點)"))
classDef default fill:transparent,stroke:currentColor,stroke-width:2px;
style x stroke:#f66,stroke-width:3px
style y stroke:#f66,stroke-width:3px
style w stroke:#66f,stroke-width:3px
linkStyle 2,3,4 stroke-width:3px,stroke:#f88
根據圖上的路徑結構,我們來比較 到 和 到 的距離:
因為我們假設了 是 的最遠點,所以 。將上方兩式代入,並消去兩邊都有的共同路徑 後,可以得出一個極為關鍵的轉折結論:
這意味著,從直徑上的 點出發,走到假想的 的距離,居然比走到直徑端點 還遠!
接著重點來了,我們用這個發現去檢驗另一個直徑端點 走到 的總距離:
將剛才得出的 代入:
也就是說,。我們居然在樹中算出了一條比直徑本身還要長的路徑 !這與「 是直徑端點」的最根本條件產生了嚴重矛盾。
(附註:若 在直徑上的相對順序相反,利用完全對稱的推導也可以精確算出 ,同樣產生矛盾)
故假設不成立,對於任意節點 ,其最遠點必定是直徑的兩個端點 或 之一。
因此,答案對每個頂點 只會是 或 之一!
演算法流程
利用上述性質,只需三次 BFS:
- 找直徑端點 :從任意頂點(例如 )做 BFS,距離最遠且編號最大者即為 。
- 找直徑端點 :從 做 BFS,距離最遠且編號最大者即為 ;同時記錄 。
- 計算第三份距離:從 做 BFS,得到 。
取完 後,確保 (若不然則交換),這樣在距離相同時選 就能滿足「取編號最大」的要求。
處理最大編號的細節
題目要求「距離相同時取編號最大的頂點」。程式碼中使用 >= 來挑選 和 (從小編號掃到大編號,>= 會不斷更新為更大的編號),並在最後確保 。這樣在 d1 >= d2 時選 就自然滿足了最大編號的需求。
樹中任意頂點的最遠點必為直徑端點之一。只需三次 BFS 求出直徑兩端 及各自到所有頂點的距離,對每個頂點取距離較大的端點即為答案。整體 。
複雜度分析
- 時間複雜度:(三次 BFS,每次 )
- 空間複雜度:(鄰接表 + 距離陣列)
Code
1 | from collections import deque |





![Luogu 🟣 P4062 [Code+#1] Yazid 的新生舞会](https://i.pixiv.cat/img-master/img/2026/04/13/04/07/06/143491427_p2_master1200.jpg)


