carnation13的树形dp学习笔记
大一时,我们在某次集训队训练时,学长就笑着调侃道:“树形dp在我们当年只是一道铁牌题,连树形dp都不会还打什么ACM”。于是乎,抱着一种好奇心,也为了能够在比赛时做出树形的题目,我便开始了树形的学习。
1|0树形 dp
2|0概念
树形,顾名思义,就是在树上,又由于树固有的递归性质,树形一般都是递归进行的。
3|0实现
既然使用递归去实现,那么我们自然需要用到函数去搜索整棵树,而对于数组的参数选择,一般选择当前枚举到的节点,并通过它的儿子节点来更新,其他维记录其他信息。
而对于树形的基本形式,已经有大佬总结出了较为模板的做法,设,其中是以为根的子树,表示在以为根的树中选个子节点,表示当前节点不选,表示选上当前节点,有时候可以压掉或者0/1这维。有关基础的方程模板
3|1选择节点类
3|2树形背包类
4|0换根 dp
树形中的换根问题又被称为二次扫描,通常不会指定根结点,并且根结点的变化会对一些值,例如子结点深度和、点权和等产生影响。
通常需要两次,第一次预处理诸如深度,点权和之类的信息,在第二次开始运行换根动态规划。
通过以上的学习,我们对于树形有了一定的了解,接下来就做点例题来小试牛刀
5|0例题
- 洛谷 P1352 没有上司的舞会
题意:一棵个节点的有向树,每个节点有权值,选出若干个节点,若选了当前节点,那就不能再选其儿子节点了,求出最大的权值之和。
思路:设表示以为根节点的子树,当前节点状态为,表示选上当前节点,表示不选该节点,所得到的最大权值。显然,状态转移方程如下
代码
- 洛谷 P1122 最大子树和
题意:一棵个节点的树,每个节点有美丽指数,通过剪掉任意多条边(也可以不剪),使剩下的子树美丽指数之和最大,求出最大值。
思路:设表示以为根的子树最大的美丽指数之和,很显然,状态转移方程如下
代码
- 洛谷 P2014 [CTSC1997] 选课
题意:现在有门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程是课程的先修课即只有学完了课程,才能学习课程)。一个学生要从这些课程里选择门课程学习,问他能获得的最大学分是多少?
思路:该题是经典的树形背包题,设表示选择以为根的子树中个节点。代表当前根节点,代表其选择的节点的总额。
代码
- 洛谷 P2015 二叉苹果树
题意:一棵个节点的树,每根树枝上有若干个苹果,现在要保留个树枝,求出最多能留住多少苹果。
思路:显然,对于每条边,有两种选择,要么剪掉这条边,要么留下这条边,所以的其中一维是树枝的数量,设表示以为节点,保留根树枝可以得到的最大苹果数,则状态转移方程
代码
- CF1187E Tree Painting
题意:给定一棵个点的树 初始全是白点
要求你做步操作,每一次选定一个与一个黑点相隔一条边的白点,将它染成黑点,然后获得该白点被染色前所在的白色联通块大小的权值。
第一次操作可以任意选点。
求可获得的最大权值。
思路:这是一道经典的换根题,先用一次求出以其中一个节点(例如1)为根,所得到的权值,该权值等于所有节点到该节点的距离之和+节点个数。得到以某节点为根的答案后,再进行状态转移,当前节点为根和其相邻节点为根有一个状态转移,(即换根的核心),表示以为根的子树其子节点深度之和,表示以为根的权值,在第一次后,我们已经求出了所有节点的,对于第二次,不难得出如下的状态转移方程
代码
- 洛谷 P3478 [POI2008] STA-Station
题意:给定一个 nn 个点的树,请求出一个结点,使得以这个结点为根时,所有结点的深度之和最大。
一个结点的深度之定义为该节点到根的简单路径上边的数量。
思路:这道题是上题的双倍经验,也是换根的经典题目,两题代码97%相同,除了输出不同,也不知道为啥难度会差一个档次,思路和上题一样,两次,第一次求出以某点为根的深度之和,第二次状态转移到以其他点位根的深度之和,最后输出最大的节点即可。
代码
- 洛谷 P2986 [USACO10MAR] Great Cow Gathering G
题意:给定一棵个点的树,每个点有只奶牛,每条边的距离长度为,选择一个节点为集会地点,定义不方便程度为其它牛棚中每只奶牛去参加集会所走的路程之和,求出最小的不方便值。
思路:这题是上两题的三倍经验,同样是一道基础的换根题,设表示以为根节点的羊数量总和,表示以为根节点的不方便值,表示羊的总数量,在第一次时,可以求出每个节点的值,以及以1为根的不方便值,第二次时,将转移,从而得到以每个节点为根时的不方便值,状态转移方程如下
代码
- CF708C Centroids
题意:给定一颗树,你有一次将树改造的机会,改造的意思是删去一条边,再加入一条边,保证改造后还是一棵树。
请问有多少点可以通过改造,成为这颗树的重心?(如果以某个点为根,每个子树的大小都不大于
,则称某个点为重心)
思路:换根经典题,相比前面3题,此题难度上了一个档次,状态转移情况比较多,这里直接上代码,细节有空再补(十有八九鸽了)
代码:
- 牛客小白月赛45 E筑巢
题意:给定你一个n个节点的树,你需要在树上选取一个非空连通块,使其舒适度和最大。选择的边和点的舒适度都是舒适度。
思路:该题是一道树形,与此题比较类似的是中的[最大连续子段和],可以设表示选了节点的连通块的最大舒适度,我们来考虑状态的转移,设表示节点自己的点权,则
另外还要考虑边界条件,若为叶子,则
代码
6|0其他例题
- 洛谷 P2585 [ZJOI2006]三色二叉树
树形简单题,部分不难,如何建树成为难题,代码实现较为简单,以下是邻接表建树的关键部分
- 洛谷 P1273 有线电视网
该题是树形与分组背包的结合体,转移方程这条边的花费不解释了,表示枚举到这一组(即的儿子),表示枚举到这组中的元素:选个用户
以下是分组背包伪代码
- CF767C Garland
树形板子题,找三个权值和相同的子树,从下往上遍历更新即可。 - CF219D Choosing Capital for Treeland
换根练手的经典题,当从某点向相邻的节点转移时,只有该两点之间的边权不同,其他边权没有变化,当向的边权为时,向的边权则一定为,反之亦然,所以可以考虑换根 - CF161D Distance in Tree
该题做法有许多,比如树上启发式合并、长链剖分、点分治(板子题)、树形等等,这里只介绍树形的做法,因为其他做法我都不会,其中关键的部分的代码如下
7|0启示
树形大多数对根和儿子进行转移,对于树上背包问题,前提要对简单的背包问题足够了解,也要注意枚举时的顺序,而换根无非就是对根进行转移,运用两次,第一次预处理,第二次转移。
完结撒花qwq
__EOF__

本文作者:carnation13
本文链接:https://www.cnblogs.com/carnation13/p/16138398.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/carnation13/p/16138398.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)