nm的树上背包
nao_nao
2020-03-10 18:27:47
我们都会树上背包 $nm^2$ 的做法,非常简单 ~~(不是)~~ ,我们只需要在每一个节点上都做一次背包即可。然而,遇到数据范围更大的树上背包,这显然是不可过的。
我们有复杂度优秀到 $nm$ 的做法。
先挂神犇[博客](https://www.luogu.com.cn/blog/P6174/solution-p2014)
我们先来造一棵树当例子(出来吧,皮卡丘!)
![这是一棵树](https://cdn.luogu.com.cn/upload/image_hosting/afrix4ub.png)
为了使用 $nm$ 的~~奇技淫巧~~,我们要对树上节点进行重编号,编号为它的[后序遍历](https://baike.baidu.com/item/%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86/1214806?fr=aladdin)序。
所以我们的树变成了这样子:
![这样子哦!](https://cdn.luogu.com.cn/upload/image_hosting/y4c3dc1z.png)
这个后序遍历序也显然有和dfs序相同的一点性质,就是同一子树的序肯定是连续的。并且可以发现,子树的根是最后加的。
我们可以按照现在点的编号来加边,$dp[i][j]$ 表示前 i 个点中选取 j 个所得到的最大价值。
我们在每一次加点的时候,可以有选与不选两种选择。如果选此点的话,我们有 $dp[i][j] = dp[i-1][j-1]+s[i]$,如果我们不选此点,那么显然我们也不能选它的子树,所以我们有 $dp[i][j] = dp[i-siz[i]][j]$,两者取$\max$即可。
虽说如此,还是要看图(图多漂亮)
我们来看一下加进去前六个点时的图:
![我也是树QwQ](https://cdn.luogu.com.cn/upload/image_hosting/0508klmr.png)
然后继续加点:
![](https://cdn.luogu.com.cn/upload/image_hosting/lbov19ho.png)
![!](https://cdn.luogu.com.cn/upload/image_hosting/u2c1mhlv.png)
![](https://cdn.luogu.com.cn/upload/image_hosting/k8rlvbha.png)
![](https://cdn.luogu.com.cn/upload/image_hosting/rrf34ydb.png)
![](https://cdn.luogu.com.cn/upload/image_hosting/80pgib1z.png)
有了这些图,你是不是能更好的理解了?
如果此文有所帮助(包括图),请点个赞吧!