树形dp

一些规律

  • 状态转移方程

    \(f[i][]\)表示\(i\)这棵子树怎样的最优解

  • 用子树更新父亲

    • 一个一个子树的更新父亲(树上背包)
    • 计算完所有子树再更新子树

题型1:子树与计数

统计子树和,通过加减一些子树满足题目中的某些性质

  • Garland

    统计以每个点为根的子树和,合并时遇到一个子树和为\(\frac{sum}{3}\)的节点就记录下来。

    code

  • 最大子树和

    统计每个点的子树和,cut数组标记删除。统计的时候每个节点都统计一次。

    code


题型2:树形背包问题

一般是让求在树上选一些点满足价值最大的问题

\(f[i][j]\)表示\(i\)这棵子树选\(j\)个点的最优解

  • 选课

    • 可能为一棵森林,添加\(0\)节点,使其变成一棵树。
    • \(f[i][j]\)表示在\(i\)及其子树中选\(j\)门课的最大得分。
    • 分组背包模型,对于一个节点\(x\),有$\left | son(x) \right | $ 组物品,每组物品有\(t-1\)个,第\(i\)组的第\(j\)个物品的体积为\(j\),价值为\(f[y_i][j]\),背包的总体积为\(t-1\)
    • code
  • 有线电视网

    • \(f[i][j]\)表示在\(i\)及其子树里满足\(j\)名用户的最大收益。
    • 统计答案时逆序枚举\(i\),如果有\(f[1][i]\)大于等于\(0\),则输出\(i\)
  • 重建道路


题型3:花费最少的费用覆盖所有点

父亲与孩子有联系

1.选父亲必须不能选孩子(强制)

2.选父亲可以不用选孩子(不强制)

  • 保安站岗

    • 属于第二类

      • \(1.\)\(x\)这个点覆盖\(x\)
      • \(2.\)\(x\)的儿子节点\(y\)覆盖\(x\)
      • \(3.\)\(x\)的父亲节点\(fa\)覆盖\(x\)
    • 分别用\(f[x][0],f[x][1],f[x][2]\)表示以\(x\)为根的子树中的所有点全部被覆盖,\(x\)的被覆盖状态分别上面的第\(1,2,3\)种状态。

    • \(f[x][0]+=min(f[y][0],f[y][1],f[y][2])+val[x]\)

      \(x\)已经被自己覆盖了,\(y\)既可以被自己或自己的儿子覆盖,也可以被\(x\)覆盖。

    • \(f[x][1]+=min(f[y][0],f[y][1])\)

      \(x\)已经被儿子节点覆盖了,\(y\)可以被自己或自己的儿子覆盖,但是不能被父亲覆盖。

      当选择的全部是\(f[y][1]\)时,要加上\(min(f[y][0]-f[y][1])\)

      \(x\)要被自己的儿子覆盖,但是\(x\)的所有儿子\(y\)都是被它的儿子所覆盖的,其实是没有儿子节点覆盖\(y\)的。此时要选一个最小的差值\(min(f[y][0]-f[y][1])\),强行使一个儿子节点选自己来覆盖\(x\)

    • \(f[x][2]+=min(f[y][0],f[y][1])\)

      \(x\)已经被父亲节点覆盖了,\(y\)可以被自己或自己的儿子覆盖,但是不能被父亲覆盖。

    • code

  • 没有上司的舞会

    • 树的最大独立集,属于第一类

    • \(f[i][0]\):在\(i\)这棵子树中,不选\(i\)的最大快乐指数。

      \(f[x][0]+=max(f[y][1],f[y][0])\)

    • \(f[i][1]\):在\(i\)这棵子树中,选择\(i\)的最大快乐指数。

      \(f[x][1]+=f[y][0]\)

    • code

  • Party at Hali-Bula

    • 树的最大独立集+判断方案是否唯一

    • \(f[i][0/1]\):在\(i\)这棵子树中不选/选\(i\)的最大人数

      \(g[i][0/1]\):在\(i\)这棵子树中不选/选\(i\)的方案是否唯一,\(g[x][0]\)\(0\)表示方案唯一,为\(1\)表示不唯一。

    • \(f[x][1]+=f[y][0]\)\(g[x][1]|=g[y][0]\)

    • \(f[x][0]+=max(f[y][1],f[y][0])\)

      • \(f[y][1]==f[y][0]\) \(g[x][0]=1\)

        已经有两种方案了。

      • \(f[y][1]>f[y][0]\) \(g[x][0]|=g[y][1]\)

      • \(f[y][0]>f[y][1]\) \(g[x][0]|=g[y][0]\)

    • code


题型4:树上统计方案问题

给一个条件,问有多少个点的集合满足这样的条件。

运用乘法原理,控制一个点不动,看它能做多少贡献

to be continued……


题型5:与其它算法结合&&大模拟

  • 风铃

    • 把题目中的要求变成公式。

    • \(mindep[i]\)表示\(i\)子树中最浅的玩具的深度

      \(maxdep[i]\)表示\(i\)子树中最深的玩具和深度

      \(dep[i]\)表示节点\(i\)的深度

    • \(f[i]\)表示\(i\)这棵子树中构成满足条件的玩具所需的操作数。

      加边时,先添加右边的玩具后添加左边的玩具,这样遍历到一个节点时,一定会先遍历右边的玩具后便利左边的玩具。

      合并时,\(f[x]=f[toy[1]]+f[toy[2]]+((mindep[toy[1]]<maxdep[toy[2]])?1:0)\)

    • \(n\)是杆的数量,不是玩具的数量……多开几倍空间

    • code

      to be continued……


参考: [树形dp+树形结构总结](

posted @ 2021-08-28 15:02  RapunzelOnly  阅读(71)  评论(0)    收藏  举报