树上dp有关的技巧

树上路径

问题描述,在一棵树上给定一些路径,每一条路径对应一个权值,现在需要选出一些路径
使得这些路径不相交,并且权值和最大

算法分析
树形 dp\text{dp} 的时候,考虑每一个点,因为每一个点有路径限制,一个点最多只能在一条路径上(也可能不在任何一条路径上)
所以尝试把在哪一条路径加入 dp\text{dp} 的维度

dp(i,j)dp(i, j) 表示点 ii 在路径 jj 上,子树能取到的最大权值,其中 j=0j = 0 对应没有路径穿过 ii
ii 的儿子记为 {v1,,vm}\{v_1, \cdots, v_m\}

特别地,这里定义路径贯穿uu,指存在路径从 uu 往它的父节点伸出来

  • 对于 j0j \neq 0,那么有路径贯穿 ii,不妨设路径 jj 贯穿了 ii 的儿子 vkv_k,那么其他儿子
    {v1,,vk1,vk+1,}\{v_1, \cdots, v_{k-1}, v_{k+1}, \cdots\}不能有路径贯穿的,可以再定义一个状态 f(u)f(u)
    表示 uu 这个节点没有路径贯穿的时候,能取到的最大权值,这样就可以写出转移方程
    dp(i,j)=(vvkf(v))+dp(vk,j)\displaystyle dp(i, j) = \left(\sum_{v \neq v_k} f(v) \right) + dp(v_k, j)

  • 对于 j=0j = 0,那么 dp(i,0)=vf(v)dp(i, 0) = \displaystyle \sum_{v} f(v)

  • 接下来考虑计算 f(u)f(u)f(u)f(u) 也有两种情况,一种是 uu 不在任何一条路径上
    第二种是 uu 处在某条路径的最高点

算法分析2
注意到给一条树上路径 (u,v,w)(u, v, w),表示从 uvu\to v 存在一条权值为 ww 的路径
注意到树上路径形式是 uLCAvu \to \text{LCA} \to v,这启发我们在 LCA\text{LCA} 处来考虑这个问题

定义 dp(u)dp(u) 表示 uu 作为 lca\text{lca} 时,uu 及其子树能够选择的最大不相交路径权值
其中,作为 lca\text{lca} 的意思就是说所选择的路径,不能伸出 uu,不能从 uu 往其祖先延伸

这样,就可以分为两类来讨论

  • 第一是不选经过 uu路径 xuyx \to u \to y,其中 u=lca(x,y)u = \text{lca}(x, y)
    这样 dp(u)=vson(u)dp(v)dp(u) = \displaystyle \sum_{v \in \text{son}(u)} dp(v),这一部分可以记为 sdp(u)sdp(u)
  • 第二就是经过 uu 的路径,此时对于 xuyx \to u \to y 所有的点 vv,不能考虑 dp(v)dp(v)
    而应该考虑把 vv 这个点删除后,剩下 vv子树构成的森林dpdp 值的和,换句话说
    对于路径 xuyx \to u \to y 的所有点 vv,此时需要考虑 vpathdp(son(v))\displaystyle \sum_{v \in \text{path}} dp(\textbf{son}(v))

具体到代码实现上,第二种情况比较难写,对于路径三元组 <x,y,w>\left<x, y, w \right>,考虑路径上每个点每个点 vv
路径如果允许相交的话,那么此时 dp(u)=sdp(u)+wdp(u) = sdp(u) + w
意思是原来的不相交路径和是 sdp(u)sdp(u),新增加了路径权值是 ww

但是该路径上每个点 vv 所对应的 dp(v)dp(v) 是不允许的,你选了路径权值 ww 就不能再考虑 dp(v)dp(v)
而应该转而考虑 dp(son(v))\displaystyle \sum dp(\textbf{son}(v)),也就是 sdp(v)sdp(v)

所以第二种情况的表达式可以简化成 sdp(u)+w+vpath(sdp(v)dp(v))sdp(u) + w + \displaystyle \sum_{v \in \text{path}}(sdp(v) - dp(v))

AtCoder Regular Contest 142