换根dp

换根dp

一般来说,我们做题的树都是默认 \(1\) 为根的。但是有些题目需要计算以每个节点为根时的内容。
朴素的暴力:以每个点 \(u\) 作为 \(root\) 暴力 \(dfs\) 下去,复杂度 \(O\left(n^2\right)\)
正确的做法:换根dp,复杂度 \(O\left(n\right)\)

执行步骤

  1. 第一次扫描,先默认 \(root=1\),跑一遍 \(dfs\)
  2. 第二次扫描,从 \(root=1\) 开始,每次从 \(u\)\(v\) 节点时,计算根从 \(u\) 转移到 \(v\) 时的贡献变化。

很显然,换根dp是在两个 \(dfs\) 中完成的,下面我们介绍一下如何运用它。

例题1 Accumulation Degree

题目链接:South Central China 2008 Accumulation Degree

Description

给你一颗有 \(n\) 个节点的树,每一条边连接 \(u_i\)\(v_i\),流量为 \(fl_i\),你需要找出一个点作为 \(root\),并最大化从该点出发到所有叶子节点的流量最大值。
多组数据。(PS:题意读不懂的可以结合题目中的图理解,类似网络流的流法)
数据范围 \(1\le n\le2×10^5\),并且 \(\sum n\le2×10^5\)
时间限制 \(1000 ms\)

Solution

我们先默认这棵树以 \(1\) 为根,跑一次 \(dfs\)。定义 \(flow_i\) 表示以 \(i\) 为根的子树中流量最大值。那么,\(u\) 节点从儿子 $v 得到的流量为:

  1. \(v\) 为叶子节点,那么 \(flow_u+=flow_v\)(可以直接流过来);
  2. \(v\) 为非叶子节点,那么 \(flow_u+=min\left(flow_v,fl\left(u,v\right)\right)\)\(u\)\(v\) 相连的边有流量限制)。

这样,我们得到了以 \(1\) 为根时的答案,记为 \(f_1\),它的值等于 \(flow_1\)。考虑如何换根。从 \(u\) 为根转移到儿子 \(v\) 为根,\(f_v\) 包括两部分:一部分是从 \(v\) 流向自己的子树,一部分是从 \(v\) 往父节点走。那么贡献的变化是第二部分造成的,原本的贡献是 \(flow_u-min\left(flow_v,fl\left(u,v\right)\right)\),现在加上 \(u\)\(v\) 这条边的流量限制,所以新的贡献是 \(min\left(fl\left(u,v\right),flow_u-min\left(flow_v,fl\left(u,v\right)\right)\right)\)。注意如果 \(u\) 的度为 \(1\),则需要特殊处理。再来一个 \(dfs\) 转移即可。复杂度 \(O\left(n\right)\) ,可以通过本题。

posted @ 2024-07-22 10:11  小熊涛涛  阅读(6)  评论(0编辑  收藏  举报