换根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