IOI2018 高速公路收费
来补一下代码,太鸽了。。。。。
https://www.cnblogs.com/Dance-Of-Faith/p/9657606.html
考虑一条链怎么做:直接二分。
一棵树怎么做:
我的第一想法是边分,找一条边 \(u,v\) 使得 \(S,T\) 在两边,然后在 \(u,v\) 向外 bfs 。
二分 bfs 序,将距离最远的一圈点变成最短路必须经过 B ,剩下的点可以只经过 A .
容易2次二分出 \(S,T\) 的位置。
需要找到这条边,边分是不太行的,可以直接二分边的列表,把 \([1,mid]\) 的边变成 B check一下距离有没有变大。
(要初始查一下全 A 的距离)查询次数 \(1+\lceil\log(130000)\rceil + \max(\lceil \log(i) \rceil + \lceil \log(90000-i) \rceil) \le 17 + 16 + 16 + 1 = 50\)
(如果要卡到 \(51\) 次,需要 \(32769+65537>90000\) 个点,所以数据范围是卡好的)
考虑图怎么做:
似乎很难做,但是根据上面的思路,如果找到一条在 \(S,T\) 路径上的边就迎刃而解。
这条边依然可以在边列表中二分。二分某个 [1,mid] 变成 B 不会增加,[1,mid+1] 变成 B 增加了就可以了。
其实这边隐含了一个优化。如果是二分了一个点出来的话,后两次二分就各需要 \(\log(90000)\) 次,就会超限。