CF196E Opening Portals
\(O(km\log m)\) 对于任意两个存在传送门的点连一条边权为图上距离的边,然后跑最小生成树。
考虑 Kruskal 的过程,其实就是多源 Prim。每次找出一个与某棵子最小生成树不连通并且距离最近的点 \(u\),将其加入这棵子最小生成树。将加入的路径对应到路径上的某条边上。具体地,对于边 \((u,v)\),我们将其端点分别修改为距离其最近的传送门,修改它的权值为两个传送门之间的距离。可以证明 Kruskal 过程中用到的路径均会对应到图中的某条边存在,并且每条边都是合法的,所以直接拿这些边跑 Kruskal 即可。

如图,假设 \(u\to x\) 是 Kruskal 过程中用到的路径,显然有 \(u\to x\) 不长于 \(u\to y\) 或者 \(y\) 已经与 \(u\) 连通且 \(u\to v\) 不长于 \(y\to v\)。之前结论的证明如下:
- 路径上的边两个端点均取不到,不可能,因为边权为正整数。
- \(u\to v\) 路径上的边均取不到 \(x\) 只能取到 \(y\),那么边一定在 \(v\to x\) 的路径上。此种情况 \(u\) 与 \(y\) 已经连通。
- 在前一种情况的基础上 \(v\to x\) 路径上的边均取不到 \(u\) 只能取到 \(y\),那么还不如换成 \(y\to x\)。不存在。
- \(u\to v\) 路径上的边均取不到 \(u\),那么当前用到的路径就不是最短的了。不存在。