树上问题学习笔记

前言:这篇博客是 yx NOIP 前恶补知识点写的,并没有普通树形 DP 捏/wq
upd:NOIP 没了,现在这里有普通树形 DP 了(

换根 DP

gg 押 NOIP 会考换根 DP,发现自己还没学过/jk
害怕.jpg

或许按本人感受的难度顺序排序(?

P3478 [POI2008] STA-Station

当根从 \(u\) 换到 \(v\) 时,\(v\) 的子树内所有节点深度 \(-1\),除此以外每个节点深度 \(+1\)。则转移方程为 \(f_v=f_u-siz_v+(n-siz_v)\)

CF1187E Tree Painting

如果已知第一个选的点作为根节点,则最优选法肯定是从上往下依次选(好像也只能这样选(?)那这样选点 \(u\) 的得分就是 \(siz_u\),最后的答案是 \(\sum\limits_{i\neq rt} siz_i\)
于是就会发现换根的转移式子和上面那题是一样的。就做完了。

P2986 [USACO10MAR] Great Cow Gathering G

依旧同理,把 \(siz\) 换成子树内 \(c_i\) 的和,转移柿子乘上边权 \(w\) 即可。

P3047 [USACO12FEB]Nearby Cows G

诈骗题。看到题想了半天怎么快速维护区间加减,然后发现自己眼瞎没看见 \(k\le 20\)...
\(f_{i,j}\) 表示以点 \(i\) 为根的子树里到 \(i\) 距离为 \(j\) 的所有点的权值和。
然后这东西 O(nk) 暴力转移就完了...
递归完要把修改过的值还原回来。

CF708C Centroids

终于有一道不一样的了
p.s.这题坑死我了。
先考虑已知根节点怎么判断合法性,那么就找到最大的子树,在这个子树里面找一个 \(x\) 使 \(siz_u-siz_x\le \frac{n}{2}\)\(siz_x\le \frac{n}{2}\)
容易想到对于每个节点维护:\(siz_x\) 子树大小,\(son_x\) 最大子树编号,\(f_x\)\(x\) 为根的子树内不大于 \(\frac{n}{2}\) 的最大子树大小(不包括 \(f_x\))。
然后你会发现这样没法 O(n) 换根 dp,因为当从 \(u\) 换到 \(v\)\(v\) 正好是 \(f_u\) 那个节点的时候就寄了。
然而本喵并没有意识到,并且在这种情况下暴力枚举 \(u\) 的所有儿子来重新求 \(f_u\) 甚至还以为它是 O(n),被菊花图成功卡 TLE/qd
于是思考并调了 1h 的代码白写了/fn
看了题解发现我们还要维护 \(f_x\) 的次大值,并保证不是从同一个儿子转移过来。
这样上面那种情况就能直接取次大值来保证复杂度。
好麻烦/kk

P6419 [COCI2014-2015#1] Kamp

顺着上一题思路想出来了,但是要维护的东西好多啊/kk
肯定是需要一个 \(cnt_x\) 来判断子树内有无关键点的。(没有就不用往里走了)
首先思考怎么走是最优的方式。假设送完最后一个人要返回出发点的话,设 \(f_x\) 为从点 \(x\) 出发走完所有关键点再回到 \(x\) 的最短路程。这个还是比较好求的,不详细写了(?
题意和上面 \(f_x\) 的区别就在最后一个人送完不用回去。那肯定挑距离 \(x\) 最远的人当最后一个,因此要维护 \(dis_{x,1/2}\) 表示到 \(x\) 子树内关键点到 \(x\) 距离的最大/次大值。
然后因为距离一样的时候没法判断是不是同一个点,还要一起维护 \(g_{x,1/2}\) 表示距离最值相对应的点的编号。
代码实现巨大多分讨,记得随时判断 \(cnt\) 是不是 \(0\) 以及 \(dis_{u,1}\) 是不是在子树 \(v\) 里。

其实还有两题要写的,但是摆了。记得抓我回来填坑。

树上背包

发现这个也不会。枯。希望现学来得及吧。

P2014 [CTSC1997] 选课

虽然以前写过,但似乎是没咋看懂式子稀里糊涂敲上去的(?
啊啊啊以前好多这种稀里糊涂照着题解思路/老师代码贺上去的题,每当提起我都记得做过,每当考到就发现不会,深受其害/ll

这题是个森林,则对每棵树的根节点向 \(0\) 连边,使之变成一棵树。
\(f_{i,j,k}\) 表示子树 \(i\) 的前 \(j\) 个儿子,已经选了 \(k\) 门课的最大值。注意:必须选点 \(i\)
那么 \(f_{now,tot,j}=\max(f_{now,tot,j},f_{now,tot-1,j-k}+f_{v,mxtot,k})\)。同样注意 \(k\) 只能循环到 \(j-1\)
类似背包进行滚动数组优化。(似乎滚动了反而更好写(?)
也不知道自己到底会没会/kk

P4516 [JSOI2018] 潜入行动

题面看起来还挺套路,但我不会,树形 dp 是真忘光了啊啊啊啊啊怎么办
式子好长不想写...算了口胡一下吧。
\(dp[u][j][0/1][0/1]\) 表示子树 \(u\) 里放了 \(j\) 个,点 \(u\) 放了/没放,是否已经被监听。
于是滚动数组一下推出长下面这样的转移柿子\(\downarrow\)

\(\begin{cases}dp[x][i+j][0][0]=\sum dp[x][i][0][0]\times dp[v][j][0][1]\\dp[x][i+j][1][0]=\sum dp[x][i][1][0]\times (dp[v][j][0][0]+dp[v][j][0][1])\\dp[x][i+j][0][1]=\sum (dp[x][i][0][1]\times (dp[v][j][0][1]+dp[v][j][1][1])+dp[x][i][0][0]\times dp[v][j][1][1])\\dp[x][i+j][1][1]=\sum (dp[x][i][1][0]\times (dp[v][j][1][0]+dp[v][j][1][1])+dp[x][i][1][1]\times (dp[v][j][0][0]+dp[v][j][0][1]+dp[v][j][1][0]+dp[v][j][1][1]))\end{cases}\)

卡 long long 空间,要强制类型转换。
我不管,我胡了就是我写了!(确信

不知道啥题

OI wiki 为什么给我推黑题啊,不会/kk
所以写到这吧awa

树形 DP

范学长讲树上问题,顺路回来更新一波。

CF822F Madness

贪心题。胡了篇 lg 题解。

P2607 [ZJOI2008] 骑士

基环树上的 dp。第一次做这种题(?
对于每个基环树,dfs 找到环的那条边,对于这条边分别钦定 \(u\) 不选/\(v\) 不选,分别 dp 即可。
转移显然。
实现的时候写麻烦了,直接并查集判环就可以,不用 dfs。

posted @ 2022-11-22 19:27  樱雪喵  阅读(105)  评论(2编辑  收藏  举报