快轉到主要內容

樹直徑

目錄

概念
#

樹直徑就是指樹上最遠的點對的距離,更仔細的說,假設有一個函式 \(dist(x, y)\) 代表節點 \(x\) 與節點 \(y\) 的簡單路徑距離,那數直徑就可以這樣表示:

\(max_{1 \leq v, u \leq n} dist(u, v)\)

以這張圖為例:

image

可以看到 1 和 2 的簡單路徑長度為 3,然後 3 到 4 的簡單路徑程度為 2,而我們要找的樹直徑是 2 到 4 這條距離為 4 的最長路徑。

實作方式
#

樹直徑的實作方式其實不只一種,而其中簡單的做法就是透過兩次 DFS,那要怎麼透過 DFS 找到樹直徑呢?

具體來說,我們需要執行以下兩個步驟:

  • 從任意點開始做 DFS 並找到最遠的那個點 \(x\)
  • 接著把 \(x\) 當起點繼續做一次 DFS 找到距離點 \(x\) 最遠的點 \(y\)

如此一來,\(x\) 與 \(y\) 的句離就是樹直徑了!

void dfs(int v, int d = 0) {
    vis[v] = true;
    // 如果深度超過目前最大深度就更新
    if (d > maxdeep) {
        // 把最遠的點記錄在 deep 變數中
        deep = v;
        maxdeep = d;
    }
    for (auto e : tree[v]) {
        if (vis[e]) continue;
        vis[e] = true;
        dfs(e, d + 1);
    }
}
 
int main() {
    dfs(1); // 第一次從任意點開始找到最遠的點
    memset(vis, 0, sizeof(vis));
    maxdeep = -1;
    dfs(deep); // 第二次從最遠的點開始找到另外一個最遠的點
    cout << maxdeep << endl; // 最後 maxdeep 就是樹直徑
}

雖然可能看似沒什麼用,不過這是非常經典的問題,APCS 檢定中也曾經直接出現過樹直徑的裸題!

Piau 的筆記本
作者
Piau 的筆記本
希望我寫下來的東西能夠長久的記在我的腦中