运输计划

luoguP2680 [NOIP2015 提高组] 运输计划

题目大意:
给出一棵树和几条路径,边有边权,可以使任意一条边边权为零,求在此之后这几条路径上边权和最大值最小是多少。
数据范围:\(1\le n,m\le 3e5 ,~t_i\le 1000\) (其中 \(t_i\) 是边权)

解法:
先说暴力:
枚举每一条边让其边权为零,然后扫一遍树,得出根节点到每个其他节点的距离(就是每条边到其祖先节点距离的前缀),最后在通过求lca得到每条路径的长度,求使当前边的边权为零时的答案,最后对着所有的答案取min。
复杂度 \(O(n~(n+m))\) 期望得分60分

之后考虑优化,发现对于上面这种思路,其中在枚举使哪条边边权为零时枚举了许多无用的状态,考虑如何对这些无用的状态进行删减。

  • 如果当这条路径的边长比当前最大的删除边权之后的路径长要短的话,那么显然不会对答案产生影响。
  • 如果当前这条边的边权比当前最大的删除边权之后减少的长度要短的话,那么显然也不会对答案产生影响。

所以,基于上面两点,我们考虑对答案进行二分。
当我们当前的mid作为答案时,满足所有 路径长比答案大 的路径的 路径长减去一条 公共的最长边 比当前答案要短的话,那么当前答案满足条件,更改当前的右端点,否则更改左端点。
解释:
1.如果当前路径长比答案短的话,那么无论这条路径上会不会有边权改为零,都不会使答案不成立,所以只需要扫路径长比答案大的路径就可以了。
2.如果减去的不是所有路径比答案大的路径的公共边,那么显然会有至少一条路径长度比答案大的路径的长度没有改变,所以答案肯定不成立。
3.如果说减去的不是公共最长边,而是其他的边的话,如果能满足条件,那么显然减去公共最长边也能满足条件(显然的贪心。

所以做法就是先求出根节点到所有其他节点的距离,
然后求出每条路径的长度,进行排序,之后二分答案长度进行判断,
如果说当前所有比答案大的路径没有公共边,或者说没有能使当前答案加上公共边使这个值比所有路径长度都大的这个样子的公共边,那么显然答案判小了,更新左端点,否则就记录答案,更新右端点。
如果说中间那个求公共边的部分用的树剖套线段树,那么复杂度为 \(O(log(\sum\limits_{i=1}^{n}{t_i})\cdot logn\cdot m)\),期望得分一百分,但是洛谷上求公共边的时候可以暴力扫,数据太水了(亲测

然后,嗯,输一下答案,就没了。
代码就不贴了,码风比较奇怪。

posted @ 2021-10-08 23:56  灵华  阅读(35)  评论(0编辑  收藏  举报