给定一棵基环树森林,起初有 m 个点已被选进 S 里,你需要再选 k 个点加入到 S 中,最小化其余点到 S 距离的最大值。
这个问题直接做非常困难,考虑二分答案转成判定性问题:选定若干个点能够使得所有点到 S 的距离不超过目前二分的答案 F。如果一个节点距离 S 中的点不超过 F,称其为被覆盖了。
基环树的题自然是树和环分开考虑,依然要预处理记好在环上的点和环上点之间的距离。如果放在树上,原题是这个,在基环树的树部分依然采用相同的 DP 方式,这个 DP 也是基于贪心的:能不放就不放。设 f_{u} 表示以 u 为根的子树中离 u 最远的没被覆盖的节点到 u 的距离;g_{u} 以 u 为根的子树中在 S 中的离 u 最近的节点到 u 的距离,那么初值为 f_{u} = 0,g_{v} = \infty,转移方程为 f_{u} = \max_{v \in son_{u}} \{ f_{v} \} + 1,g_{u} = \min_{v \in son_{u}} \{ g_{v} \} + 1。接下来考虑一些边界情况:
如果当前点 u 本身就在 S 中,有 g_{u} = 0,原因显然。
如果 f_{u} + g_{u} \leq F,这说明用 u 子树中的 S 中的点就可以覆盖整棵 u 的子树,u 对 u 的祖先们没有决策影响了,那么 f_{u} = -\infty。
如果 f_{u} + (u,fa_{u}) > F,如果 u 点不选入到 S 中,那么距离 u 最远的那个未覆盖节点就要不合法了,所以必须将 u 选入到 S 中,那么 f_{u} = -\infty,g_{u} = 0,同时选点数量计数器要加一。
对于环上每个点为根做一遍这个树形 DP,可以得到树中最少需要选多少个点,以及根据根节点 i 的 f_{i} 值和环上边长来知道必须要在环上的某一段区间内选点进入 S 才能使得 i 子树内的和 i 距离最大的未被覆盖的节点合法。特别的,如果环上存在一个节点 j,使得 f_{i} + g_{j} + dis_{i \to j} \leq F,即用 j 子树中的离 j 最近的 S 中的点来覆盖 i 中的点,那么对于 i 就不会存在环上的这段选择区间。这一部分的形态形如寻找前后缀 a \pm b 的最小值,可以用前缀 \min 线性解决。找环上的需要被覆盖的区间可以先算出最深的不合法节点到根节点的距离,然后推出在环上的延伸距离,由于我们预先处理好了环上边权的前缀和,就可以在前缀和上做一个二分查找来找到区间的左右端点。
解决上述步骤之后,现在问题转化成了在环上有若干个区间,每个区间至少选一个点,问最少要选多少个点。由于起初的 m 个点有一些可能在环上,先把这些点能满足的区间去掉。然后可以运用这个题的套路,加入当前选择了一个位置 i,能够发现下一个选择的节点一定是左端点大于这个节点,且右端点最靠左的那个区间的右端点,可以用单指针线性求出从位置 i 开始下一个选择的位置在哪里,然后预处理倍增数组 st_{i,j} 表示选择了位置 i,下 2^j 个位置选在哪里,枚举哪个节点作为第一个选择的节点,倍增的算接下来总共在环上要选几个点,于是这样就 \mathcal O(n \log n) 的解决这个部分了。