树形DP

Up and Down DP

如何求解从一个点到其它地方的路径长度信息?

点分治

可以使用 Up and Down DP

将路径分成两类, 向上走以及向下走, 进行简单的维护, 进行两次 \(dfs\)

[NOI2012] 迷失游乐园

先计算树的情况, 使用 Up and Down DP

\(ans_u = \frac{down_n \times son_u + up_u \times fa_u}{son_u + fa_u}\)

先一遍 \(dfs\) 求解 \(down\)

\(down_u = \frac{1}{son_u} \sum (down_v + w_{u, v})\)

再一遍 \(dfs\) 求解 \(up\)

\(up_u = w_{u, k} + \frac{up_k \times fa_k + down_k \times son_k - down_u - w_{u, k}}{fa_k + son_k - 1}\)

是不是非常优美的转移式子

基环树环很小, 直接暴力枚举计算 \(up\) 就可以了

Tree MST

考虑 \(B\) 开头的最小生成树算法

那么我们需要求解一个连通块向外连的最小边, 我们也就是要求一个点向外连的最小边

使用 Up and Down DP 对于可能连通块相等的情况, 可以再记录一个最小值

树上背包

[CTSC1997] 选课

和背包一样

主要说一下的复杂度 \(O(nm)\)

注意要对子树的大小取 \(min\)

如果不取的话, 复杂度其实是 \(O(nm^2)\)

树上依赖性背包

如果不能对子树的大小取 \(min\)

我们两个数组的卷积复杂度是 \(O(m \times m)\)

但如果是一个数组与一个值的复杂度就是 \(O(m)\)

若干个值卷起来就是 \(O(n \times m)\)

我们显然可以通过控制 \(n\) 来到达一个比较好的复杂度, 所以有下边的思路


我们只要求根的话, 我们有一种做法

我们想要只卷 \(n\)

就是考虑 \(dfs\)

我们设 \(f_{i, j}\) 表示 \(dfs\)\(\ge i\) 的方案

考虑如果选择可以从 \([i + 1, n]\) 转移

如果不选择可以从 \([i + sz_i, n]\) 转移

这是 \(dfs\) 序的特性

复杂度 \(O(n)\)

如果需要求很多点呢?

  • 点分治

这个比较显然

复杂度 \(O(nmlogn)\)

  • dus on tree

我们要用 \(f_{i, j}\) 算出 \([i, i + sz_i - 1]\) 的方案

它的若干个儿子把序列分成了若干份, 我们肯定也想要 \(O(n \times m)\) 样子的复杂度

所以, 我们考虑把一个一个的值卷起来, 不难想到 dsu_on_tree

复杂度就是 \(O(nmlogn)\)

Shopping

一类统计链的树形 DP

核心思想

就是分情况讨论, 考虑当前节点与当前节点儿子之间的贡献, 把复杂的问题拆成比较简单的几个问题

例1

给定一棵 \(n\) 个点的树, 找到树上的两条边不相交的路径, 使得删去路径上的所有点和边后剩下的连通块数量最多, 输出最大个数

\(n \le 5 \times 10^5\)

考虑树形 \(DP\) 考虑当前节点与他的儿子节点构成答案的所有可能情况

这三种情况

发现第一二种情况只需要维护经过自己的一条最优方案, 和不经过自己的子树内的一条最优方案

但是第三, 四种情况, 分别可以通过 \(u\) 中的一条经过 \(u\) 链和 \(u\) 子树中的一个方案加上 \(v\) 中的一条经过 \(v\) 的链||\(u\) 中的一条 经过 \(u\) 链和 \(v\) 中的一条经过 \(v\) 的链加上 \(v\) 子树内的方案拼接而成

所以设如下状态

\(f_{u, 0}\) 是为了更好的转移

那么我们来考虑如何维护这个东西吧

先是 \(f_{u, 0}, f_{u, 1}, f_{u, 2}\)

\(f_{u, 0} = \max\{f_{v, 0} + son_u - 1\}\)

\(f_{u, 1} = \max\{f_{v, 1}, f_{v, 2} + 1\}\)

\(f_{u, 2} = \max\{f_{v,0} + f_{u, 0} + 1\}\)

都是比较容易理解的

比较复杂度是 \(f_{u, 3}\)

考虑链是那里的, 不是 \(v\) 子树的:

\(f_{u, 3} = \max\{f_{v, 1} + f_{u, 0} - 1, f_{v, 2} + f_{u, 0} - 1\}\)

\(v\) 子树的, 再考虑 另一条最优路径是哪里的, 不是 \(v\) 子树中的

\(f_{u, 3} = \max\{f_{v, 0} + f_{u, 2} - 1\}\)

剩下一种需要注意一下, 因为 \(f_{u, 1}\) 我们并不知道它是 \(u\) 的直系儿子, 还是二代以后的, 所以我们并不好处理连通块的个数, 所以采用 \(tmp = \max\{f_{v, 1}, f_{v, 2}\}\)

\(f_{u, 3} = \max\{f_{v, 0} + tmp + son_u - 2 \}\)

\(v\) 子树中的

\(f_{u, 3} = \max\{f_{v, 3} + son_u - 1\}\)

由于链可以退化成点, 路径可以退化成链

\(f_{u, 2} = \max\{f_{u, 0}\}, f_{u, 3} = \max\{ f_{u, 2}\}\)

然后是统计答案

第一二种情况

\(f_{u, 1} + f_{v, 2}\)

\(f_{u, 1} + f_{v, 1} - 1\)

\(f_{u, 2} + f_{v, 1} - [u==1]\)

\(f_{u, 2} + f_{v, 2} - [u==1]\)

第三种情况

\(f_{u, 3} + f_{v, 0} - [u==1]\)

第四种情况

\(f_{v, 3} + f_{u, 0} - [u==1]\)

初始化方面

\(f_{u, 0} = f_{u, 2} = f_{u, 3} = son_u, f_{u, 1} = 1\)

[六省联考 2017]摧毁“树状图”

例2

在树上寻找 \(k\) 条点不相交链,并且最大化这 \(k\) 条链的边权之和

前边是 wqs二分

后边自己想, 和上边是差不多的

[八省联考 2018] 林克卡特树

拆边贡献

这是树形 \(DP\) 常见的

换根 \(DP\)

一遍 \(dfs\) 求出一些信息以及此时根的答案, 第二遍 \(dfs\) 开始换根

posted @ 2025-02-16 19:33  d3genera7e  阅读(20)  评论(0)    收藏  举报