換根DP學習筆記


今天打 \(Atcoder\) 時遇到了一道換根 \(DP\) ,發現自己不太會,學習了一下。

一般來說,這類題在做樹形 \(DP\) 時沒有固定的根,可以枚舉根然后做 \(N\) 次樹形 \(DP\) ,但復雜度是不太優的,於是有了換根 \(DP\),一般通過兩次對整棵樹的 \(dfs\) 遍歷來求解,復雜度一般是線性的。

還是用例題來直觀講解吧。

[POJ3585] Accumulation Degree

題意

有一個 \(n\) 個結點的樹形水系,每條 \(u->v\) 邊有一個容量 \(C(u,v)\) ,任意一個點都可以作為起點,樹中每個度數為 \(1\) 的結點都可以作為終點,求最大流量。
(其實就是求樹的最大流)
\(n\le10^5\)

Solution

(直接上網絡流還是算了吧)
先思考朴素的 \(DP\) 解法,枚舉樹根 \(S\) ,對每個 \(S∈ [1,n]\) 做一次樹形 \(DP\) ,設 \(dp[i]\) 表示當前流向以 \(i\) 為根的子樹的最大流量,那么轉移方程很好寫。

\[dp[i]=\sum_{u∈son[i]} \begin{cases} C(i,u)& \text{deg[u]=1}\\ min(dp[u],C(i,u))& \text{deg[u]> 1} \end{cases}\]

時間復雜度 \(O(N^2)\),過不了本題數據。

發現此題滿足換根的特征,考慮換根 \(DP\)

\(f[i]\) 表示以 \(i\) 為根流向整顆樹的最大流量,如果我們能線性計算出 \(f\) 數組,那么我們的答案只需要取 \(f\) 中的最大值。

任選一個點為根,做一次普通的樹形 \(DP\) 。然后考慮這樣一件事,對於一條邊 \(u->v\) ,現在 \(f[u]\) 的值已經被求出,如何計算出\(f[v]\) 呢?

顯然,已經知道了一個重要的信息,從 \(u\) 結點流向整顆樹的最大流量,而從 \(u\)\(v\) 的流量(也是到 \(v\) 子樹內所有葉子結點的最大流量和)是 \(min(d[v],C(u,v))\) ,那我們除去這一部分,得到的就是 \(u\) 到除了 \(v\) 所在子樹的流量和,現在我們進行一個神奇的操作,令 \(v\) 為整棵樹的根。

那么我們就會發現這樣的事情, \(u\) 成了 \(v\) 的一個兒子,且子樹和是 \(f[u]-min(d[v],C(u,v))\) ,這條邊流量仍然是 \(C(u,v)\)

我們有換根的方程:

\[f[v]=dp[v]+ \begin{cases} C(i,u)& \text{deg[u]=1}\\ min(f[u]-min(d[v],C(u,v)),C(i,u))& \text{deg[u]> 1} \end{cases}\]

\(f[v]\) 的值就表示樹根從 \(u\) 換成 \(v\) 的結果,時間復雜度 \(O(N)\)

我們發現,這種問題的一般特征是,通過一次整體的,固定根的樹形 \(DP\) 對整體進行一個求解,這個過程是自下而上的,再通過自上而下的換根操作,關注將一條邊的端點進行換根的影響,因為已知上面的點在全局的值,除去子樹貢獻,可以方便轉移。

參考文獻

李煜東.《算法競賽進階指南》. 二次掃描與換根法

[HDU2196] Computer

題意

給你一棵 \(n\) 個點的樹,輸出以每個頂點為根節點,到樹上點的邊權和最大,輸出這個最大值。

Solution

初看這道題,可能會像上一道題一樣,考慮換根時除去子樹貢獻,但這題要求取 \(max\) ,而不是求和,不好拆分,這類題,就需要在記錄最大值同時,記錄一個次大值,然后就可以換根轉移了,和求樹的直徑是一樣的,這題所有答案取最大值就是這棵樹的直徑,復雜度 \(O(N)\)

\(f[i][0]\) 表示點 \(i\) 到以它為根的子樹的最遠點的距離

  \(f[i][1]\) 表示點 \(i\) 到以它為根的子樹(並且這個子樹與最遠點所在子樹不相同)的次遠點的距離(一會會用到)

  \(f[i][2]\) 表示除去點 \(i\) 的子樹后,點 \(i\) 到離它最遠的點的距離

  \(val\) 表示邊權

那么 \(f[v][2]\) 怎么求?(\(u\) 表示 \(v\) 的父親)

  \(if(f[v][0] + val[i] == f[u][0])\) \(f[v][2] = f[u][1] + val[i];\)

  \(else\) \(f[v][2] = f[u][0] + val[i];\)

  \(f[v][2] = max(f[v][2], f[u][2] + val[i]);\)

那么一個點 \(i\) 到它的最遠點的距離即為 \(max(f[i][0],f[i][2])\)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM