题目描述
H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,
也是树中的根节点。
H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境
城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境
城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,
首都是不能建立检查点的。
现在,在 H
国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等
于道路的长度(单位:小时)。
请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。 输入输出格式 输入格式:
第一行一个整数 n,表示城市个数。
接下来的 n-1 行,每行 3 个整数,u、v、w,每两个整数之间用一个空格隔开,表示从
城市 u 到城市 v 有一条长为 w 的道路。数据保证输入的是一棵树,且根节点编号为 1。
接下来一行一个整数 m,表示军队个数。
接下来一行 m 个整数,每两个整数之间用一个空格隔开,分别表示这 m 个军队所驻扎
的城市的编号。
输出格式:
共一行,包含一个整数,表示控制疫情所需要的最少时间。如果无法控制疫情则输出-1。
可以贪心地考虑,每个军队都会尽量向上走,因为每走一步控制的点只多不少。只有在到达根之后才考虑下到别的子树,而且只下一步【也就是走到根的儿子】。
首先倍增预处理出祖先和距离。
很明显可以二分答案。
对于给定时间,如果一支军队能到达根就上到根备用,不能上到根的标记驻守节点。
从根开始dfs一遍,对于每个没有被完全看守的根的儿子,找到剩余时间最小的回不来的那支军队【如果有的话】留在这里,否则就记录下来。
把所有需要被看守的根的儿子和所有尚未使用的军队排序之后尝试配对,成功则说明当前时间合法。
为什么对于没有覆盖的根的儿子要找回不来的进行看守呢?首先这样做不会使解变得更差,因为能回来的军队在最后一步还是可以回来。其次,如果这支军队能走很远,而这个节点到根的距离很近,这支军队就浪费掉了。让一个能走的不太远的别的子树上的军队来到这里,再让这个军队去一个更远的地方可能是更优的解。而让另一个军队来到这里,那个军队至少要能走这个点到根的距离这么长的路,也就是“换位”过来的军队的“能力”至少是这个点到根的距离。当且仅当留在这里的军队的“能力”不到这个点到根的距离【也就等价于这个点回不来】,才不会丢失解。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
const int mx=