Problem’s Website
Solution
首先这是一道NOIP的压轴题。
题面好长啊,不少废话,一句话题意:
给定一棵树和m个任务(从$u$点到$v$点),可以使树上的一条边边权为0,让这m个任务中边权之和的最大值最小。
最大值最小? 那岂不是可以……
没错,我们可以二分答案。
那怎样检查答案的正确性呢?
我们不妨现将每个任务的权值和求出来,然后升序排序,如果当前的mid比最大值还大,那显然没有意义,在有意义的情况下,我们从小到大进行树上差分,最后枚举判断一下每一条边是否可以减少,判断一下如果修改后的最大值不大于当前mid,说明权值还可以缩小,否则就不能再缩小。
看到这,大家肯定有很多疑问,我们一一来解答
- 如何求每个任务的权值和?
权值和还是比较好求的,我们在树剖的第一个dfs中记录一下点到根中路径的权值和,那么公式为$dis[u] + dis[v] - 2 \times dis[LCA(u, v)]$,LCA我们不需要倍增求,直接用树剖记录的$top$数组求即可。
2.为什么要进行树上差分?
如果是一条满足条件的边修改为0,那么一定存在所有的其他需要修改的航道都经过了这条边(要不然他们就不会减少了),所以要进行树上差分。
这道压轴题就愉快地AC了!
Code
1 |
|
rp++