题目大意
\(n\)(\(n\leq2*10^5\))个点,\(m\)(\(m\leq4*10^5\))条边的图,每条边有海拔\(a_i(a_i\leq10^9)\)、长度\(l_i(l_i\leq10^4)\),定义两点\(a,b\)距离为从\(a\)走到\(b\)至少要走的长度之和
\(q\)组询问,强制在线,每次给出
\(v,p\),表示询问不走
\(a_i\leq p\)的边,从
\(v\)出发能走到的与
\(1\)号点距离最近的点到
\(1\)号点的距离
题解
预处理每个点到\(1\)号点的距离
每次询问相当于在问删掉所有
\(a_i\leq p\)的边,点
\(v\)所在连通块中到
\(1\)号点最小的距离
发现只考虑原图的最大生成树上的边,不会改变连通性
点
\(v\)所在连通块之所以到不了别的点集,是因为它们之间在最大生成树上的路径中有一条边
\(a_i\leq p\) 考虑kruskal的过程,相当于有一次是用一条
\(a_i\leq p\)的边合并了点
\(v\)所在连通块与其他点集
这样就可以以这种方法建一新棵树:一开始有
\(n\)个点,没有边,kruskal中每合并两个点集,就新建一个表示当前边的点,并且将两个点集新树中的根变成新建点的儿子
新树中一个点的子树表示这个点对应的原图的最大生成树中一条边kruskal时合并的两个点集,也就是说,这个子树中任意两点的路径中不会出现边权小于该边的边
所以每次询问在新树中找
\(v\)的深度最小的
\(a_i> p\)的祖先
这个新树也叫kruskal重构树
代码
#include #include #include #include #include #include #include #include #include