题目大意:给出一个DAG,要求删掉一个点之后使最长路最小,求删掉的点和最长路长度。
给出题人跪了orz
先考虑不删点的情况。想求一个图的最长链,在DAG应尝试DP,但起点、终点都不能固定,怎么转化呢?既然会求固定起点与终点的最长链,就强制固定一个点让其在此开始或结束,因此想到设置一个超级源S与超级汇T,求S到T的最长链后减2即为答案1。
下面考虑删除点。枚举每一个点将其删除,求得图中最长链,就要想办法快速地维护删点以后图的最长链。
感觉这里真的好神啊…可以预处理出每一个点到S、T的最长距离,那么每一条边的起点到S的最长距离与终点到T的最长距离都已知。这样就可以用一条边赋上权值来表示经过这条边的最长路,这样就可以用若干条边中最大的来表示出图中的最长路。要怎么选取边才能保证这些边代表的最长路包含图中的最长路呢?
当图中从起点到终点的所有路径都要经过选取的边时,经过这些边的最长路中就一定包含图中的最长路,也就是说最长路即图的一个割集中边权的最大值。
为了维护割集可以维护两个集合:S集和T集2。按照拓扑序删点。初始状态下,将S点视为已经删除,可以从图中任一点出发到达T,即所有点处于T集中。然后,将拓扑序的下一个点,从T集中删掉,就是把这个点的所有入边以及这个点到T的最长路删掉,此时的最大值就是删掉这个点的答案,再将这个点加入S集,就是把这个点的所有出边以及S到这个点的最长路加进去,表示把这个点重新加回来。
动态维护一些值的最值可以使用堆或是权值线段树。
#include <cstdio>
#include <cstring>
#include <queue>
#define Max(a,b) (a>b?a:b)
#define N 1001005