树形 DP
简单的树上 dp 其实已经在普及组涉及过:自上而下和自下而上传递的性质。
现在我们需要研究更复杂的树上 dp,比如换根 dp 等等。
【树上 dp】
给出一棵带点权的树,求这棵树中的最大权连通块。
因为是无根树,我们人为规定 1 号结点为根。
我们发现,“最大权连通块的点权和” 是一个可以自下而上传递的属性。对于每一个结点
我们先递归处理
现在我们求出了
对于这个问题,我们的处理是:
为什么正确呢?因为我们考虑任何一个连通块,无论这棵树以谁为根,它一定有一个深度最浅的点
给定一颗无根树。如果我们在
我们令 1 号结点为根。
显然所有
下考虑一个结点
-
。因为 不放,所以与 相连的边都需要靠 的子结点瞭望。所以 。 -
。 放了,那么子结点就可以考虑放与不放。显然每个子结点的子树之间没有关系。所以 。
这题有点像树上背包,但并不是树上背包。
这题相当于给出了一片
我们可以考虑建一个 0 号点,作为每棵树的根的父节点,同时也是根节点,权值设为 0。
定义:
初值:
递推:
对于一个结点
可是这样写感觉很奇怪,因为
注意,这里我们递推完
所以,我们最后还需要枚举
答案是
【换根 dp】
对于一颗无根树,我们可以考虑固定一个结点为根来求出以这个点为根的答案。但是我们可能需要知道每一个点为根的答案,如果每一个点做根都重新求一遍答案,这就太慢了。
我们可以考虑 “换根 dp”。
具体而言,当我们当前做根的结点是
这个时候我们发现一件事:对于所有
而父节点子树变化的地方在于:增加了
如果我们能快速计算这一部分产生的贡献,并将其传递给子结点,我们就可以让子结点快速计算变化的量。
给出一颗无根树,每条边有一个容量,所有叶结点(度为 1)都是汇点。求以哪个点为源点(根)时,从每个汇点流出的水量之和最大。当然汇点不能同时做源点。
先假设 1 是根节点(源点)。
我们令
显然对于每一个点
接下来我们考虑
而
而
所以
最后还有一个问题,就是关于叶结点当根的问题。我们可以让
一般换根 dp 都会有两次循环,一次计算以一个点为根的答案,另一次用换根计算每一个点为根的答案。
给出一棵树,可以删去一条边再补上一条边,请问对于每一个点,是否能通过操作使其变成中心。
显然对于一个点,如果它不是重心,意味着它恰有(不恰有,加起来大于
显然,我们要从最大的子树中,切下一个规模
我们关心一颗子树中 一个规模
考虑如何用
求
"切与
“切
还有一个要注意的点:我们要去掉子结点通向父节点的边。
【环形 dp】
Naptime G(这个是环形 dp,为后面基环树 dp 做准备)
注:如果只睡一个时间,不增加效用值。如果睡了连续多个时间,从第二个时间开始计算效用值。
我们从简单情况开始,考虑我们在线性怎么做这个问题:
之所以要开第三维
接下来我们考虑环形,因为环形交界处在
-
第
段不睡,正常线性,取 (第 段必须不睡); -
第
段睡,唯一的影响是如果第 1 段睡就会变成有效睡眠,取 (第 段必须睡)。
因为
这两种情况我们可以做两次 dp,唯一的区别是如果第
【基环树 dp】
基环树:一棵树,加上一条边(
给出一棵基环树,每个点有点权。相邻两点不能同时选。选出若干个点使得点权和最大。
首先,我们可以找出这个环。然后我们枚举环上每一个点,这个点下方吊着一棵树。而在树上这个问题是很简单的,类似 “战略游戏”。
对于环上每个点都做完这个操作之后,我们可以用环上每个点代表这个点吊着的树,可以这么做的原因是环上每个点是否选择,并不影响环上其他点吊着的树。
于是我们就可以做一次环形 dp,第
和上面的题类似,我们可以讨论最后一个数选还是不选,做两次 dp。
还有一个问题:怎么
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!