标签:dfs 覆盖 父亲节 距离 多点 独立 复杂度 题意 最小
参考课件和讲授来自Accelerator
树的直径定义为一个树中最长的一条链。
对于第一种做法比较适合拓展到其他形式的 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, 分类讨论即可。
前面默认我们都是使用了 DFS 来递归处理子树,然后回溯更新节点,但是实际操作中会存在问题。
Windows 下默认栈空间大小为 4Mb, Linux 下为 8Mb, 大量递归会堆栈溢出。
考虑这个转移的过程只需要所有的儿子都被更新完
。我们BFS 这颗树,然后按照bfs序倒过来处理 DP 是可以得到同样的效果的。
至此我们解决了这个问题。
标签:dfs 覆盖 父亲节 距离 多点 独立 复杂度 题意 最小
原文地址:https://www.cnblogs.com/tyner/p/11405667.html