B. Fake Plastic Trees
什么时候才能会做贪心题啊 😢。
首先给出几个 observation:
- 以点 \(u\) 为链底进行操作,给 \(u\) 设置的增量一定是在使 \(u\) 的权值不超过 \(r_u\) 的情况下最大的值;
- 当 \(u\) 的所有子树均取最优操作数时,\(u\) 也总是取最优操作数。这是因为若存在子树没取最优操作数,一定至少多了一次操作,但是多的这一次操作显然不如直接在 \(u\) 上操作优。
基于此可以设计一个 \(\rm dfs\),往回传最优操作数条件下的最大增量,若小于 \(l_u\),就再新增一次操作,将值提到 \(r_u\).
C. Keshi in Search of AmShZ
感觉这题还是蛮妙的?突然发现自己没学懂 \(\rm dijkstra\) /jk.
首先容易产生一个想法:只保留从 \(1\) 到 \(n\) 最短路上的边,其它的边都 \(\rm block\) 掉。这个想法的 motivation 在于 \(\rm block\) 边的花费只有 \(1\),同时非最短路一定比最短路 至少多 \(1\).
然而这个策略是有问题的。考虑某个点 \(u\) 有两个后继 \(v,w\),若 \(v\) 是从 \(1\) 到 \(n\) 最短路上的点,\(w\) 不是,按照上文的策略应该 \(\rm block\) 到 \(w\) 的边。然而如果 \(v\) 有很多非最短路上的后继咋办?这时我们应该进行权衡,说不定直接 \(\rm block\) 掉 \(v\) 反而会更优。
基于此设计一个类 \(\rm dijkstra\) 的算法:记 \(d_i\) 为从 \(i\) 到 \(n\) 最坏情况的最小花费,同时连上反向边,记 \(\text{deg}_i\) 为点 \(i\) 反向边的入度。从 \(n\) 开始跑 \(\rm dijkstra\),对于反向边 \((v,u)\),若 \(d_v+\text{deg}_u<d_u\),则更新 \(d_u\),同时将 \(u\) 的入度减一。最后答案就是 \(d_1\).
考虑到在 \(\rm dijkstra\) 的过程中,从队列中取出点 的距离标记一定是不降的。那么对点 \(u\) 而言,若将它的后继按 \(d\) 从小到大排序(也即从队列中取出点的顺序),想要取到第 \(i\) 个后继对应的 \(d\),就必须把排在第 \(i\) 个之后的后继全都 \(\rm block\) 掉[1],同时还有 \(1\) 的边权,所以边权为当前 \(\text{deg}_u\).
这里其实不太严谨,不过当 \(d\) 相同的时候取排在最后面的那一个肯定是最优的。 ↩︎