洛谷P1084 题解
本文最后更新于 2025年1月2日 晚上
知识前置
倍增算法
本题用于倍增跳祖先,检查可行性。详见OI-Wiki。
二分算法
满足单调性的答案求解,本题用于二分答案查找最少时间。详见OI-Wiki。
树上DFS遍历
自己学去。
贪心算法
本题中用于匹配军队与子树。详见OI-Wiki。
题目描述
更详细的描述,请前往洛谷查看。
树上根节点$1$爆发疫情,需要军队前往其它节点(不能是根节点)建立检查站,防止疫情扩散到叶子结点。
一支军队只能建立一个检查站,行军时间为边的权值。
军队原驻扎节点和树上距离已给出,求控制疫情所需的最小时间,若无法控制输出$-1$。
数据范围:$2\le m\le n\le5\times10^4$,$0\le w\le1\times10^9$
题目分析
答案求解
注意到答案是单调的,即可行的解都连续且在一侧。
考虑使用二分答案求解,寻找可行条件下的最小时间。
问题转化为二分的check()
函数,即对于给定的时长,确定疫情是否能被控制。
军队移动
显然,需要控制根节点的疫情,军队应尽可能朝向根节点移动,以最小化检查点数量。
军队向根节点移动一定是百益而无一害的,因为这是一棵树。
军队本来可以隔离的根节点,依旧在军队下方,建立检查点后可以受到隔离。
上移过程中,还可能覆盖其它叶子结点,增加隔离范围。
算法实现
由于时间已给定,可以先让军队向根节点移动,而不前往根节点。
此时军队有三种:
1.距离根节点仅剩一条边,并且剩余时间可以前往根节点。
2.距离根节点仅剩一条边,但是剩余时间不能前往根节点。
3.连根节点的边都没碰到,还在路上的。
对于第一种情况的军队,前往根节点并记录来时的子树。对于后两种情况的军队,在原地建立检查站并打上标记。
接着对每一棵子树,DFS从根节点自上而下遍历到叶子节点。如果路径上没有驻扎,标记该子树。
为这些子树分配军队,策略如下:
1.优先选择自己子树来的且剩余时间较短的。这些军队实质上相当于上述第二种的军队,临近根节点后原地建立检查站。
2.优先选择剩余时间较短的匹配所需时间较长的,以节省军队使用,保证正确性。
对于上述两策略,不难发现应先对子树和军队排序,子树按所需时间降序,军队按剩余时间升序。
双指针从前向后遍历子树和军队,满足下列条件之一即可匹配:
1.军队剩余时间可以到达子树。
2.军队从该子树过来的。
若匹配成功,换下一棵子树和下一支军队。若匹配失败,则换下一支军队。
如果按照上述策略匹配,还有子树没有分配到军队,则证明给定的时长下问题无解,反之则有解。
答案输出
分析得,时间大于$5\times10^5$即可认为无解。所以二分左端点$0$,右端点$5\times10^5$。
若可行,更新答案为中间端点,右端点左移。若不可行,左端点右移。
代码实现
AC 15.36MB 203ms
1 |
|
总结
二分找答案,贪心判断可行性,倍增优化。