CF1051F 题解
CF1051F 题解
分享一个来自sjx巨佬的线性做法,如果有什么错误之处敬请指出。
题意就不说了,我直接讲做法。
首先建出原图的最小生成树,那么余下的非树边只有之多 条,
我们将所有非树边的左右端点记为关键点,并将这些关键点两两间的 也标记成关键点。
我们发现,由 产生的新关键点小于关键点数,因为:
我们将原关键点按 序升序排序,再将所有排序后相邻的关键点对的 标记成关键点,
容易证明,这样标记后,任意两个关键点的 都已经是关键点了。
这些关键点只有不超过 个,我们可以预处理原图中所有关键点间任意两个的最短路,
具体来说,我们建一个只与关键点有关的新图 ,
对任意两个关键点 ,我们往 中加一条 的边,权为两点在生成在树上的距离。
然后,对于所有连接两个关键点的非树边,我们将这些边也加进 中。
我们在这张图中计算出任意两点间的最短路,
就等价于计算出了原图中任意两个关键点间的最短路。
为方便接下来的叙述,我们称关键点为黑点,非关键点为白点。
此时,树上的黑点将所有白点划分成了若干个连通块,
那么对于一组询问 ,
我们只需要找到所有与 所在的连通块接壤的黑点 ,
再找到所有与 所在的连通块接壤的黑点 ,那么这组询问的答案就是:
,其中 代表关键点对 间的最短路。
当然,如果点 或点 本身就是黑点的话,与 或 接壤的黑点就只有自己。
看上去现在的复杂度仍然不低,但实际上我们可以证明 以保证复杂度。
我们需要证明的,实际上是:
对于任意一个白点构成的连通块 ,与其接壤的黑点不超过两个。
那么,我们在这个连通块中随意挑一个点 ,沿着 的祖先链往上走,可以走到至多一个黑点;
同时,点 的子树中不可能存在大于等于两个黑点,否则这个连通块中必然存在至少一个黑点,
因为两个黑点的 也是黑点,这与连通块中全是白点的条件矛盾,
故与一个连通块接壤的黑点不超过两个。
那么,对于每组询问,我们暴力的计算 ,最后将 和 在树上的距离取 即可。
我们用树剖查询 ,用你知道的任意一种快速求最短路方式求关键点间的最短路,
而求图中的最小生成树,
我们可以用基数排序或者tarjan发明的随机数据期望线性最小生成树算法发现,
实际上我们可以用图中的任意一棵生成树代替,都不会影响答案的正确性。
而求图中的任意一棵生成树,我们直接 即可。
这样复杂度就是 或 ,
取决于你的全源最短路使用的是立方级别的算法还是平方带 级别的算法。
当然,在 很小时,这个算法的表现是线性的。
所以理论上是不是可以出一道边数减点数为300,询问数为1e7的的加强版?
代码可以在 上看sjx的,ta的用户名叫 (让我们由衷地感谢这位巨佬)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】