若还没有把“连通块合并”和割性质连起来,先完成 课前零食:只修够用的路。
学完后,你应能证明 Kruskal/Prim,使用割性质安全削减完全图候选边,并用超级源把“选设施或连线”统一成生成树。
前置:并查集、排序、连通图。
最小生成树(Minimum Spanning Tree, MST)连接全部点、无环且边权和最小。两条互补性质是:
Kruskal 按权从小到大,只在两个不同并查集间加边;每步用割性质安全扩展。Prim 则维护已选点集与外界的最轻边,同样是割性质。两者区别主要是图的表示:稀疏边表适合 Kruskal,能按需计算点到集合代价的稠密图常适合 $O(n^2)$ Prim。
long long 或更宽类型。$2\le N\le10^5$ 个平面城镇,坐标至 $10^9$,可连接任意两城,费用为 $\min(|x_i-x_j|,|y_i-y_j|)$。求连通全部城镇的最小费用。
按 $x$ 排序加入相邻对,按 $y$ 再加入相邻对,共 $O(N)$ 条候选边。对完整图任一割,取最轻跨割边 $(u,v)$,设其费用由 $x$ 差实现。沿 $x$ 排序从 $u$ 到 $v$ 的区间中必有一对相邻点跨该割,坐标差不超过 $|x_u-x_v|$,其真实费用又不超过坐标差。因此候选图在每个割上都含一条不比完整图最轻边更重的边,Kruskal 可得到同样最优权。
复杂度 $O(N\log N)$,空间 $O(N)$。
candidates = []
sort towns by x; add every adjacent pair
sort towns by y; add every adjacent pair
give each candidate its true min(|dx|, |dy|) cost
output Kruskal(candidates)
完整 GNU C++17 参考实现见附件:AtCoder-arc076_b.cpp
若费用改成 Manhattan 距离,单纯保留 $x/y$ 相邻边不再成立;需使用按象限变换的候选边生成等不同工具。
$n\le2000$ 个城市。城市 $i$ 建电站花 $c_i$;连接 $i,j$ 花 $(k_i+k_j)(|x_i-x_j|+|y_i-y_j|)$。每城需建站或经电线连到有电城市,求最小费用并输出电站与电线。
任何供电方案的每个连通电网至少有一个电站;把每座电站连到超级源后得到连通图,可删环而不增费用成为生成树。反之超级源 MST 去掉源后,每个分量恰通过至少一条站边获电。因此方案与生成树最优值一致。
先把每城到当前树的最小费用初始化为建站费用,父亲记为 -1。每次加入最便宜城市,再用它到其余城市的电线费用更新。父亲 -1 表示电站,否则输出电线。复杂度 $O(n^2)$,空间 $O(n)$。
treat building station i as edge super_source-i with cost c[i]
initialize Prim key[i] = c[i], parent[i] = super_source
repeat n times:
select unused city v with minimum key
record station if parent is source, otherwise record wire
update every unused city's key by wire_cost(v, city)
output total and recorded construction
完整 GNU C++17 参考实现见附件:CodeForces-1245D.cpp
若规定恰建 $K$ 座电站,就不再是普通 MST;可考虑给站边统一加参数做 WQS 二分,但需要证明站数随参数单调。
$n,m\le2\times10^5$。任意两点 $x,y$ 可花 $a_x+a_y$ 连边,另有 $m$ 条指定优惠边。求连通全部点的最小费用,$a_i,w\le10^{12}$。
对任意割,设全局最小点 $p$ 在左侧,右侧普通边最便宜端点为 $v$。边 $(p,v)$ 的费用不大于任意普通跨割边。因此星形候选保留了每个割最便宜的普通选择;优惠边全部保留后,候选图足以由割性质得到原问题 MST。
边数降到 $m+n-1$,复杂度 $O((n+m)\log(n+m))$。
hub = vertex with minimum a[hub]
candidates = all special offers
for every v != hub: add ordinary edge hub-v with cost a[hub]+a[v]
output Kruskal(candidates)
完整 GNU C++17 参考实现见附件:CodeForces-1095F.cpp
本题能削成星是因为普通边权可分离为 $a_x+a_y$。若是 $a_xa_y$ 且含负数,或附加距离项,割上的最便宜端点结构会改变。
Built? 为什么只保留坐标相邻边仍覆盖每个割?Make It Connected 的星形削边依赖哪种可分离结构?先手写 Kruskal 并与枚举生成树对拍小图。三题都要求先写“任意割上保留了什么边”的证明再编码;做完后改变费用公式,主动构造候选边削减失效的最小反例。