11.8时空传送

来源:互联网 发布:java 线程局部变量 编辑:程序博客网 时间:2024/05/10 16:09

Problem

有一个有n个点m条有向边的有向无环图,问删掉某个点后最长路最小变成多少。

Solution

可以发现,我们麻烦的地方在于,有可能我们删掉一个点之后,会有造出一条完全不相关的最长路(即与原本最长路没有交集)。
假设我们现在删掉了点x,那么观察任意一条路径,我们必定可以将其分成两部分(可能某一部分是空的),前一部分的点的拓扑序在x之前,后一部分的点的拓扑序在x之后(注意是严格的“之前”“之后”),这样就保证了不会包含点x,设所有拓扑序在x之前的点为S集,在x之后的点为T集,于是我们可以维护所有从S集连到T集的贡献,显然这只需要预处理一下以每个点为结尾的最长路f[x]和以每个点为开头的最长路g[x],当然还有可能最长路的路径不包含S或T集中的点,那么同样的也维护S集中的点的f[x]和T集中的点的g[x]就好了,我们使用堆来维护这样的最大值。
更形象的,我们画个图来解释一下:
一开始我们的图是这样的:
这里写图片描述
其中蓝色的表示S集,绿色的表示T集,红色的表示从S集到T集的连边。
那么现在在堆中的值应该是蓝色点(S集)的f值、绿色点(T集)的g值,以及所有红色连边的贡献((u,v)的贡献应该是f[u]+g[v]+1)。
现在我们尝试将x从T集移到S集并计算删掉x的答案。
首先将所有到x的有向边删掉(为什么不用删掉从x出发的有向边?因为此时只有红色边在堆中),并将x的g值在堆中删除,于是图变成了:
这里写图片描述
于是当前堆中的最大值就是删掉x的最长路。
现在尝试将x移到S集中,将x的出边都放进堆中,并将x的f值也放进去,于是图变成了:
这里写图片描述
于是我们可以按照拓扑序来加点到S集中,这样就可以完美解决了。

1 1
原创粉丝点击