令P
为 各个路径上所有边权和 path
, 所有的n-1
条边记作: e1, e2, e3, ...
, 比如:
P1 = e1 + e3 + e4 + ...
P2 = e2 + e3 + e5 + ...
P3 = e1 + e2 + e5 + ...
将一个ei
(某一条边), 置为0后, 新的 各个路径PP1, PP2, PP3, ..
求: max( PP1, PP2, PP3, ...)
的最小值.
看到 最少, 自然想到 二分.
令Check( mid)
为: 将 某一条边权 置为0后, max( 所有的 路径和)
是否是 <= mid
的. (如果是, 则r = mid
)
这个定义自然是正确的.
错误思路
PPi > mid
(MAi
为PPi
路径上的 最大边权),MAi <= (PPi - mid)
, 则说明 有解.很容易这样想…
… 但是, 所有路径的MAi
, 并不是同一条边呀…
正确思路
依旧是二分, Check
的定义也依旧不变.
但一定要考虑一个核心问题: 我们只能选择同一条边, 将其置0,
令MA_PP = max( PPi)
(即所有路径的最大值)
对于mid
, 假设要置0的边为: E_choose
… 结论1: 则一定有: E_choose >= (MA_PP - mid)
, 这点非常关键!
我们只需考虑所有PPi > mid
的路径, 假设这些路径是: PP1, PP2, ..., PPk
这些路径都是非法的, E_choose
必须 同时在这些路径里!
因此
… 1, 建立树上对(边)的差分Diff
(初始均为0)
… 2, 将PP1, ..., PPk
这些路径上的 所有边, 都执行+= 1
操作.
… 3, 将Diff
恢复为Diff_sum
则, 同时出现在PP1, ... ,PPk
这些路径上的边, 一定被 += 1
了 k
次.
因此: 遍历所有的边 (其实遍历点就行, 因为差分的边权是在点上)
如果该边Diff_sum == k
且 该边的Wth
边权 >= (MA_PP - mid)
, 两个条件, 则该边就是E_choose
思路就是这样的, 不算太复杂.
但操作比较多.
得到PPi
需要用: 对(边权)的 树上前缀和.
将路径上所有边执行+= 1
, 需要进行 对(边)的 树上差分, 然后再恢复
而且, 还需要通过点 获取边权值
;
优化点
MA_PP - max_edge, r = MA_PP
(max_edge
为 所有边的最大边)