ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

树型DP(2)

2019-08-24 19:00:58  阅读:233  来源: 互联网

标签:子树 一个点 更新 son 树型 节点 DP


声明

参考课件和讲授来自Accelerator

找树的直径

树的直径定义为一个树中最长的一条链。

  1. 一种做法比较显然,我们可以大力 DP,维护出一个节点向下的最长链F(x)和次长链G(x),保证F,G不出自同一个儿子,然后用二者加和来更新答案,同时更新父亲节点的最长链和次长链
  2. 另外一种做法,则可以这样:随便选择一个点,然后找到距离这个点最远的点 A, 再以 A 为源点,找到距离 A 最远的一个点 B, AB 路径上的点就是直径。

对于第一种做法比较适合拓展到其他形式的 DP 上去,更新时维护次小的想法也比较适合推荐。同时可以求出任意一个子树的直径
第二种方法我们可以拿出一些有利于解题的性质
第二种方法不支持负权,这需要注意下。

找树的重心

对于一棵 n 个节点的无根树,找到一个点 A,使得把树变成以该点为根的有根树时,最大子树的结点数最小。A 叫做重心。

求法很简单,求 size 即可。

容易发现重心的各个儿子的 size<= \(n/2\)

支配集与独立集

1.求一个最大点集使得其中点的个数尽可能多且该集合中不存在两个点有边相连
2.求一个最小点集使得树上的每个点都存在一个集合中的点与其相连
两个问题很有代表性,这里讲一下解法。

第一个问题比较好解决,考虑令 f(x) 表示 x 点在集合中以x 为根的子树能选取的最多点数,g(x) 表示x 点不在集合中,以 x 为根的子树能选取的最多点数。
考虑按照题意的合法性转移即可。
f(x) = ∑g(son)
g(x) =∑ max f(son), g(son)

第二个问题相对复杂,我们称选择的点能够“覆盖”与其相连的点,那么考虑一个点的合法状态有 3 种,分别设选则该点的状态为 f(x),这个点被儿子覆盖g(x), 这个点被父亲覆盖h(x)f, h 函数的转移都很简单对于 g, 分类讨论即可。

DP 的两种处理方法

前面默认我们都是使用了 DFS 来递归处理子树,然后回溯更新节点,但是实际操作中会存在问题。
Windows 下默认栈空间大小为 4Mb, Linux 下为 8Mb, 大量递归会堆栈溢出

考虑这个转移的过程只需要所有的儿子都被更新完。我们BFS 这颗树,然后按照bfs序倒过来处理 DP 是可以得到同样的效果的。

至此我们解决了这个问题。

树形 DP 为什么相较其他 DP 来比有难度

  1. 在树上进行,相较于序列,更新的方式更多,对思维难度和代码实现难度要求都更高。
  2. 对 DP 优化的考察更为明显,如何通过更优秀的状态表示将一个复杂度更高的动态规划降维
  3. 背包问题的拓展以及树上背包
    接下来我们将通过习题来解决这些问题。

标签:子树,一个点,更新,son,树型,节点,DP
来源: https://www.cnblogs.com/tyner/p/11405667.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有