CF1051F 题解

CF1051F 题解

分享一个来自sjx巨佬的线性做法,如果有什么错误之处敬请指出。

题意就不说了,我直接讲做法。

首先建出原图的最小生成树,那么余下的非树边只有之多 \(21\) 条,

我们将所有非树边的左右端点记为关键点,并将这些关键点两两间的 \(LCA\) 也标记成关键点。

我们发现,由 \(LCA\) 产生的新关键点小于关键点数,因为:

我们将原关键点按 \(dfs\) 序升序排序,再将所有排序后相邻的关键点对的 \(LCA\) 标记成关键点,

容易证明,这样标记后,任意两个关键点的 \(LCA\) 都已经是关键点了。

这些关键点只有不超过 \(83\) 个,我们可以预处理原图中所有关键点间任意两个的最短路,

具体来说,我们建一个只与关键点有关的新图 \(G'\)

对任意两个关键点 \(u,v\) ,我们往 \(G'\) 中加一条 \(u\rightarrow v\) 的边,权为两点在生成在树上的距离。

然后,对于所有连接两个关键点的非树边,我们将这些边也加进 \(G'\) 中。

我们在这张图中计算出任意两点间的最短路,

就等价于计算出了原图中任意两个关键点间的最短路。

为方便接下来的叙述,我们称关键点为黑点,非关键点为白点。

此时,树上的黑点将所有白点划分成了若干个连通块,

那么对于一组询问 \((u,v)\)

我们只需要找到所有与 \(u\) 所在的连通块接壤的黑点 \(p1,p2,\cdots,p_i\)

再找到所有与 \(v\) 所在的连通块接壤的黑点 \(q1,q2,\cdots,q_j\),那么这组询问的答案就是:

\(ans=\min\limits_{x\in[1,i],y\in[1,j]}dist(p_x,q_y)\),其中 \(dist(u,v)\) 代表关键点对 \(u,v\) 间的最短路。

当然,如果点 \(u\) 或点 \(v\) 本身就是黑点的话,与 \(u\)\(v\) 接壤的黑点就只有自己。

看上去现在的复杂度仍然不低,但实际上我们可以证明 \(i,j\in[0,2]\) 以保证复杂度。

我们需要证明的,实际上是:

对于任意一个白点构成的连通块 \(T\),与其接壤的黑点不超过两个。

那么,我们在这个连通块中随意挑一个点 \(s\),沿着 \(s\) 的祖先链往上走,可以走到至多一个黑点;

同时,点 \(s\) 的子树中不可能存在大于等于两个黑点,否则这个连通块中必然存在至少一个黑点,

因为两个黑点的 \(LCA\) 也是黑点,这与连通块中全是白点的条件矛盾,

故与一个连通块接壤的黑点不超过两个。

那么,对于每组询问,我们暴力的计算 \(ans\),最后将 \(ans\)\((u,v)\) 在树上的距离取 \(\min\) 即可。

我们用树剖查询 \(LCA\),用你知道的任意一种快速求最短路方式求关键点间的最短路,

而求图中的最小生成树,

我们可以用基数排序或者tarjan发明的随机数据期望线性最小生成树算法发现,

实际上我们可以用图中的任意一棵生成树代替,都不会影响答案的正确性。

而求图中的任意一棵生成树,我们直接 \(dfs\) 即可。

这样复杂度就是 \(O((m-n)^2\log(m-n)+n+m)\)\(O((m-n)^3+n+m)\)

取决于你的全源最短路使用的是立方级别的算法还是平方带 \(\log\) 级别的算法。

当然,在 \(m-n\) 很小时,这个算法的表现是线性的。

所以理论上是不是可以出一道边数减点数为300,询问数为1e7的的加强版?

代码可以在 \(CF\) 上看sjx的,ta的用户名叫 \(songjiaxing\)(让我们由衷地感谢这位巨佬)。

posted @ 2022-02-08 15:20  GaryH  阅读(53)  评论(0编辑  收藏  举报