这几天看了dp中的树形dp的部分,并且做了几道题。

     一般的dp是在线性结构中,在树形结构中的dp是比线性结构中dp效率高的,而在树形结构是很有利于做递归的所以树形dp很多都是递归来实现。

     一般的树形dp中的递归有两种(目前见过两种),1先递归子节点,再利用子节点信息更新本结点信息。2先更新本结点信息,再递归子节点。

     题型也是不少,我也见识了不少了。

1  树的最大独立集,

    其实就是当选择了一个节点后,它的父亲节点和子节点是不能选择的,所有就是至少要间隔1个节点才能选择。这样组合的集合的价值最大的就是最大独立集。

    一般这种题直接一次dfs遍历即可。在一次遍历中,每次递归本结点的选择会影响子节点的选择,这里就是有dp的味道了。

2  树的重心类

    树的重心是,与重心相连的所有子树中,结点数最多的子树   是所有节点的最多子树中最少的。

    一般这类题是要求输出重心的节点是什么,或者重心的最大子树的节点树量是多少(暂时叫做额度)。

    最多加一点限制条件,比如节点的号码要按从小到大输出,或者输出所有的额度小于结点数一般的结点。

3  树的背包。

   这个和线性上的背包差不多,结点信息会有需要花费多少东西才会获得多少价值之类的东西,然后需要进行循环。

   树上的背包前一个状态和后一个状态的关系是在书上的,就是父节点和子节点的关系。一般用第一种递归实现,然后在本结点实现剩下的循环背包就可以了。

4  树的最大距离

    一棵树的最大距离很简单,在刘汝佳的白皮书上有说明,也就是首先要把无根树转化为有根树,然后从根节点进行dfs遍历即可,找出离根节点的最大距离和次大距离,加起来即可。

   还有一种是输出所有结点的最大距离,这个就要进行两次dfs遍历才行。

   第一次dfs,求每个节点在它儿子方向的最大距离,即从该节点往下出发(叶子方向),找最大距离。
   这次dfs利用孩子节点的信息跟新本节点的最大距离和次最大距离。
   第二次dfs,求每个节点在它父亲方向的最大距离,即从给节点往上走(根的方向),找最大距离。
   这次dfs利用本结点跟新孩子节点最大距离和次最大距离。

5 删除边形成p结点的子树

   其实这个和背包问题非常相似,我感觉可以堪称背包问题把,把删除的边当作价值,把子树的结点数当作花费。(只是随便一说)

   也是按照结点间的关系,枚举这p个结点是来自子节点还是父节点。然后dp。

    

   也可以说这些都是一种类型,树形dp。。。qaq