1. 程式人生 > 其它 >樹的直徑及其陰間變式總結

樹的直徑及其陰間變式總結

\(\texttt{Part 1}\) 樹的直徑問題

問題描述:

給出一棵樹,求出它直徑的長度。

\(\texttt{SOLUTION}\)

這個問題不必多說,兩種演算法(證明略,程式碼略)。

  • 演算法一:兩遍 dfs
    • 第一遍:任定一個根 \(rt\) ,找到距離 \(rt\) 最遠的點 \(st\)
    • 第一遍:以 \(st\) 為根,找到距離 \(st\) 最遠的點 \(ed\)\(st\)\(ed\) 之間的距離即為樹的直徑。
  • 演算法二:樹形 dp。
    • 隨機一個根進行 dp ,用 \(dp_{i,0}\) 表示,在以 \(i\) 的子樹中,\(i\) 到葉子節點的最大距離,\(dp_{i,1}\)
      表示,在以 \(i\) 的子樹中,\(i\) 到葉子節點的次大距離。
    • 最終答案即為 \(\max{dp_{i,0}+dp_{i,1}}\)

例題:

\(\texttt{Part 2}\) 樹的直徑問題 \(+\) 求出所有樹的直徑都經過的邊數

題目描述:

給出一棵樹,求出它直徑的長度,以及所有直徑都經過的邊的條數。

\(\texttt{SOLUTION}\)

我們設 \(dis_{u,v}\) 表示樹上節點 \(u\) 到節點 \(v\) 的距離。

首先看第一問,求樹的直徑。見上文\(……\)這裡略。

再看第二問。先看圖,假設我們第一問求出的直徑為加粗的那些點構成的鏈。

我們發現,\(dis_{1,2}=dis_{2,7}\),這意味著下圖中的這些點也能成為樹的直徑。

所以,節點 \(2\) 左邊的邊一定不是所有直徑都經過的。

同理,\(dis_{4,6}=dis_{4,9}\),所以節點 \(4\) 右邊的邊一定不是所有直徑都經過的。

所以我們只要將第一問中求出的樹的直徑上的節點記錄下來。

再求出如下圖所示以樹的直徑上的點 \(x\) 為根的這些子樹中,根到葉子的最大距離 \(mdep_{x}\)

以及節點 \(x\) 到直徑左端點和直徑右端點的距離\(ldis_x\)\(rdis_x\)。然後將 \(mdep_{x}\)\(ldis_x\)\(rdis_x\) 作比較,排除一定不是所有直徑都經過的邊,即可求出第二問的答案。

例題

\(\texttt{Part 3}\) 刪除任意一條邊後兩棵樹的直徑

題目描述:

給定一棵樹,對於每一條邊,把這條邊刪掉之後得到的兩棵樹的直徑是多少?

\(\texttt{SOLUTION}\)

對於這個問題,首先,我們需要預處理未分割前樹的直徑以及樹的直徑上的節點。

然後對以樹的直徑兩端為根分別跑一遍 dfs 。這個 dfs 要維護的資訊為:以任意節點 \(x\) 為子樹的的直徑。

最後,我們就可以愉快的分類討論了。

  • 當刪除的邊在樹的直徑上時:兩棵子樹均可直接查詢。

  • 當刪除的邊不在樹的直徑上時:有一棵子樹的直徑一定是未刪邊之前的樹的直徑,另一棵子樹則可直接查詢。

\(\texttt{AC CODE}\)

\(\texttt{Part 4}\)

\(\texttt{Part 5}\)

基環樹樹的直徑問題

\(\texttt{Part 6}\)

\(\texttt{Part 7}\)

動態刪邊樹的直徑問題。