換根dp

cn是大帅哥886發表於2024-08-17

大致步驟


換根dp 大致步驟

方法一:(up陣列)
(1) g[i] 以i為根的子樹(不是整棵樹),由孩子節點推過來
(2) up[i] i節點往上走的最大屬性
(3) f[i] 整棵樹(不是子樹) 記錄一些值

方法二:加減法

(1) g[i] 以i為根的子樹(不是整棵樹),由孩子節點推過來

(2) f[i] 整棵樹(不是子樹) 記錄一些值(透過加減法,用g陣列計算f陣列)

這就是一些通用套路了,下面會詳細講解如何使用

深度最大(方法一)


第1題 深度最大 檢視測評資料資訊

給定一個 n 個點的樹,請求出一個結點,使得以這個結點為根時,該樹深度最大。深度定義為葉子節點到根的簡單路徑上邊的數量最大值。1≤n≤1e6,1≤u,v≤n

輸入格式

第一行有一個整數,表示樹的結點個數 n。

接下來 (n−1) 行,每行兩個整數 u,v,表示存在一條連線 u,v 的邊。

輸出格式

輸出一行一個整數表示你選擇的結點編號。如果有多個結點符合要求,輸出節點編號最小值。

輸入/輸出例子1

輸入:

2

1 2

輸出:

1

樣例解釋

例題1(換根1:up陣列)

g(i, 0/1):以i為根的子樹,0:次大深度,1:最大深度
通常記錄最大的情況下,要記錄次大值


第一步. O(n)

如何更新次大值,最大值?
假設v是i的子樹,子推父

1) if (g[v][1]+w >= g[i][1])
g[i][0]=f[i][1], g[i][1]=g[v][1]+w //注意順序,先更新最大值,再更新次大值
son[i]=v //後面解釋

2) if (g[v][1]+w<f[i][1])
g[i][0]=max(g[i][0], g[v][1]+w)

3) 最重要的陣列:
son[i] 以i為根的子樹,是哪個兒子給i最大貢獻


第二步. O(n)

怎麼更新up陣列?
up[root]=0
父推子,假設i是u的孩子,i-u直接相連的邊權值為w

分情況,u往上走,u往下走
1) up[i]=max(w+up[u], up[i])

u往下走的最遠距離,是不是i往上能走到的?那不就是最遠距離了嗎,但是要注意u走過的路徑不能和i重疊,不然i就變成往下走了,所以如果重疊,換次長路,這是肯定不會經過i
2) if (son[u]==i) up[i]=max(up[i], w+g[u][0])
else up[i]=max(up[i], w+g[u][1])


第三步

f[i]=max(g[i][1], up[i])
ans=max(ans, f[i])

相關文章