树形 dp 做题记录

P3177 [HAOI2015] 树上染色

  • 考虑每一条边的贡献,就会发现这个贡献其实只和子树内的黑点的数量有关

  • 那么设 \(dp[u][num]\) 表示 \(u\) 节点子树内有 \(num\) 个黑点的最大收益

P2607 [ZJOI2008] 骑士

  • 可以发现最后的图就是一个基环森林,考虑一颗基环树怎么解决

  • 对于一颗基环树,考虑找到环上的一个点,然后断开换上的一条边

  • 然后就是一颗树了,对于一棵树就很好求了,最后我们强制根节点不选,那么答案仍然是合法的

  • 还有种情况就是强制那个和根之前相连的节点不选,然后再做一次,这样答案仍然合法

P4438 [HNOI/AHOI2018]道路

  • 看到一个条件,对于一个乡村可以通过不超过 40 条路到达首都

  • \(f[u][i][j]\) 表示节点 \(u\) 上面修建了 \(i\) 条公路和 \(j\) 条铁路,子树种的最小值

  • 那么每次先便遍历子树,然后对于自己枚举 \(i,j\) ,然后有两种选择,一种是修建左边,一种是修建右边

P1131 [ZJOI2007] 时态同步

  • 对于一个节点,自己祖先的路径只会统一修改自己的子树,所以我们对于每个节点,都要将自己所有的儿子修改到同一个时间

P1270 “访问”美术馆

  • 因为每条路要被走 2 次,所以一开始权值乘二

  • 对于每个节点维护 \(dp[u][time]\) 表示从这个节点下去还剩 \(time\) 的时间能得到的最多的画

P2491 [SDOI2011] 消防

  • 这个路径一定是在直径上,那么就可以把这个题目抽象成一个序列(直径)上的问题

  • 可以考虑用尺取法确定一个区间,对于这个区间的最大值就是左边右边中间,左右的可以预处理,对于中间的可以考虑单调队列维护

  • 那么整体的复杂度就是 \(O(n)\)

  • 我一开始想的是二分,但是麻烦一点

P4253 [SCOI2015]小凸玩密室

  • 这个题目一个很不好做的点在于有后效性,也就是当前的选择会影响到后面的选择

  • 对于一个节点为开始的话,肯定是先点亮自己,然后点亮一颗子树,再点亮另一颗子树,然后再点亮父亲,点亮父亲的另一颗子树,点亮父亲的父亲....

  • 对于这个节点不只要考虑子树中要是最小,还要考虑从子树中的一个叶节点到达父亲的一个路径长度

  • 既然有后效性,那么我们就将这个后效加入到状态中(事实上对于这一类有后效的 dp 可以考虑加上后效这一状态,或者更简单的直接加上会对后面造成的影响)

  • 对于一个叶子节点,下一步要么走到一个祖先,要么走到一个祖先的另一个儿子

  • 那么对于两者我们都保存,因为是一个完全二叉树,所以只会有 \(\log\) 的祖先

  • \(f[u][i]\) 表示节点 \(u\) 遍历自己的子树完了后从子树中的一个叶子节点,到达第 \(i\) 个祖先的最小价值

  • \(g[u][i]\) 表示节点 \(u\) 遍历自己的子树完了后从子树中的一个叶子节点到达第 \(i\) 个祖先的另一个儿子的最小价值

  • 状态设出来了,转移方程就从儿子转移

  • 考虑最后一个节点作为第一个点亮的节点,那么这个节点肯定是先点亮自己的子树,然后点亮父亲,点亮父亲的另一个儿子,然后点亮父亲的父亲

  • 而这个过程很明显可以用我们刚刚求的数组来解决

  • 对于每个节点都假设为最初的节点

  • 总的复杂度就是 \(O(n\log n)\)

一些小 trick

  • 看到树了,考虑一下树形 dp

  • 一般都会有结点这个维度,一般都是考虑一个子树,然后考虑怎么从儿子转移

  • 完全二叉树的高度是 \(\log\)

posted @ 2022-06-04 10:05  Kzos_017  阅读(30)  评论(0编辑  收藏  举报