CF1051F 题解

CF1051F 题解

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

我们只需要找到所有与 u 所在的连通块接壤的黑点 p1,p2,,pi

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

ans=minx[1,i],y[1,j]dist(px,qy),其中 dist(u,v) 代表关键点对 u,v 间的最短路。

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

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

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

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

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

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

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

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

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

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

而求图中的最小生成树,

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

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

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

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

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

当然,在 mn 很小时,这个算法的表现是线性的。

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

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

posted @   GaryH  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示