学习笔记——树形DP

· · 个人记录

树形DP的懵逼学习

现状:有点感觉

最近更新时间: 2019.09.07 12:10

树形DP题目:

  1. [ 福建省历届夏令营 ] 没有上司的舞会
  2. 选课
  3. 战略游戏
  4. [ ZJOI2008 ]骑士
  5. [ USACO10MAR ] Great Cow Gather
  6. [ SDOI2011 ] 消耗战

    基本模型:

    • 从根到叶节点:

      通常来说,要完成初始化/收集数据,一般是从根节点一路遍历到叶节点,于此同时顺便初始化,即把类似 f [ u ] [ v ] [ 1 ] 的迭代基础给打好,或者在所有操作前就做好初始化

    • 从叶节点到根:

      一般来说这是一个状态转移的过程,即类似 f [ u ] [ v ] = max ( f [ u ] [ v ] , f [ u ] [ k ] + f [ k + 1 ] [ v ] +somethings ) 的过程

    • 一般存的是单向图,毕竟是一棵树
    • 树形DP中遍历的顺序主要与存边顺序有关
    • 如果是无向图,就使用child和father的方法遍历图
    • 不一定都是先遍历后DP,看实际情况 [ USACO10MAR ] Great Cow Gather

      解题报告:

Type 【1】 选课

Type 【2】 [ ZJOI2008 ]骑士

Type 【3】 [ USACO10MAR ] Great Cow Gather

① 所有的牛首先到达了1号节点

② 3号节点以及他子树上的节点都需要退回1->3的路径的长度

③ 除了3号节点以及他子树上的节点都需要前进1->3的路径的长度

Type 【4】 [ SDOI2011 ] 消耗战

虚……虚树优化?!——王蒟蒻

1.割掉 i,其实它们就都被割掉了,代价为f [ i ]

2.对一些 j 进行割边,将代价累和∑f [ j ]

  1. 如果depth [ lc ]>=depth [ s [ top-1 ]:

a. 如果lc==s [ top ]:

那什么都不用操作,因为剪掉栈顶元素同时也剪掉了lc

b. 如果不是:将lcs [ top ] 连起来 ,若lc!=s [ top - 1 ],它一定在s [ top ]s [ top - 1 ] 之间:

如果lc == s [ top - 1 ]:

栈顶元素弹出即可

  1. 如果depth [ lc ]<depth [ s [ top-1 ]:

stak [ top − 3 ] −> stak [ top − 2 ] −> stak [ top − 1 ] −> stak [ top ] 变成了stak [ top − 3 ] −> lc −> a。我们需要循环依次将最右链的末端剪下,将被剪下的边加入虚树,直到不再是该情况。

就上图而言,循环会持续两轮,将stak [ top ] ,stak [ top − 1 ]次出栈,并且把边tak[top−1]−>stak[top],stak[top−2]−>stak[top−1] 加入虚树中。随后通过情况二完成构建。 即把

Add(s[top-1],s[top]);  
                    top--;
  1. 最后统一把a压入栈中