<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Minimum Spanning Tree |</title><link>https://sichen-wang.github.io/tags/minimum-spanning-tree/</link><atom:link href="https://sichen-wang.github.io/tags/minimum-spanning-tree/index.xml" rel="self" type="application/rss+xml"/><description>Minimum Spanning Tree</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Sat, 24 Jun 2023 11:00:56 +0000</lastBuildDate><image><url>https://sichen-wang.github.io/media/icon_hu_9dfcb674aa885f38.png</url><title>Minimum Spanning Tree</title><link>https://sichen-wang.github.io/tags/minimum-spanning-tree/</link></image><item><title>最小生成树</title><link>https://sichen-wang.github.io/blog/%E6%9C%80%E5%B0%8F%E7%94%9F%E6%88%90%E6%A0%91/</link><pubDate>Sat, 24 Jun 2023 11:00:56 +0000</pubDate><guid>https://sichen-wang.github.io/blog/%E6%9C%80%E5%B0%8F%E7%94%9F%E6%88%90%E6%A0%91/</guid><description>&lt;h2 id="kruskal"&gt;Kruskal&lt;/h2&gt;
&lt;p&gt;最常用且大部分情况下效率最高的最小生成树算法。&lt;/p&gt;
&lt;p&gt;将边按长度从小到大排序，每次贪心选择最短的一条边，若这条边连接的两个点还为连通，则将两个点所在的连通块用这条边连接，连通块用并查集维护。&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;证明: 使用归纳法，证明任何时候 Kruskal 算法选择的边集都被某棵 MST 所包含。
基础: 对于算法刚开始时，显然成立（最小生成树存在）。
归纳: 假设某时刻成立，当前边集为 \(F\)，令 \(T\) 为这棵 MST，考虑下一条加入的边 \(e\)。
如果 \(e\) 属于 \(T\)，那么成立。
否则，\(T+e\) 一定存在一个环，考虑这个环上不属于 \(F\) 的另一条边 \(f\)（一定只有一条）。
首先，\(f\) 的权值一定不会比 \(e\) 小，不然 \(f\) 会在 \(e\) 之前被选取。
然后，\(f\) 的权值一定不会比 \(e\) 大，不然 \(T+e-f\) 就是一棵比 \(T\) 还优的生成树了。
所以，\(T+e-f\) 包含了 \(F\)，并且也是一棵最小生成树，归纳成立。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;时间复杂度 \(\Theta(m\log m)\)。&lt;/p&gt;
&lt;h3 id="kruskal-重构树"&gt;Kruskal 重构树&lt;/h3&gt;
&lt;p&gt;这是 Kruskal 算法除了求最小生成树以外的一个重要应用。&lt;/p&gt;
&lt;p&gt;在使用 \(\rm kruskal\) 最小生成树算法的时候会从小到大加入 \(n-1\) 条边。现在仍按照这个顺序，每次加入一条边时将其变成一个点权等于边权的点，然后把它作为所连接两个连通块的父亲节点。&lt;/p&gt;
&lt;p&gt;不难发现两个结点在 MST 上的最短路径上的边权最大值为它们在 \(\rm kruskal\) 重构树上 \(\rm LCA\) 的点权，并且从一个点 \(u\) 出发只经过边权小于某值的边能够到达的点集为 \(\rm Kruskal\) 重构树上某点的子树内所有的叶子结点。&lt;/p&gt;
&lt;h2 id="prim"&gt;Prim&lt;/h2&gt;
&lt;p&gt;在稠密图上复杂度最优的最小生成树算法。&lt;/p&gt;
&lt;p&gt;与 Dijkstra 算法类似，选择一个点作为起点，每次选择到&lt;strong&gt;当前已选的点集中任意一个点&lt;/strong&gt;距离最短的未选择的点并向其连边，再递归操作。&lt;/p&gt;
&lt;blockquote class="border-l-4 border-neutral-300 dark:border-neutral-600 pl-4 italic text-neutral-600 dark:text-neutral-400 my-6"&gt;
&lt;p&gt;证明: 还是说明在每一步，都存在一棵最小生成树包含已选边集。
基础: 只有一个结点的时候，显然成立。
归纳: 如果某一步成立，当前边集为 \(F\)，属于 \(T\) 这棵 MST，接下来要加入边 \(e\)。
如果 \(e\) 属于 \(T\)，那么成立。
否则考虑 \(T+e\) 中环上另一条可以加入当前边集的边 \(f\)。
首先，\(f\) 的权值一定不小于 \(e\) 的权值，否则就会选择 \(f\) 而不是 \(e\) 了。
然后，\(f\) 的权值一定不大于 \(e\) 的权值，否则 \(T+e-f\) 就是一棵更小的生成树了。
因此，\(e\) 和 \(f\) 的权值相等，\(T+e-f\) 也是一棵最小生成树，且包含了 \(F\)。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;时间复杂度 \(\Theta[(n+m)\log n]\)。&lt;/p&gt;
&lt;h2 id="boruvka"&gt;Boruvka&lt;/h2&gt;
&lt;p&gt;在大多数完全图上求最小生成树所使用的算法。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每次遍历所有的点，求出它当前属于哪个连通块。&lt;/li&gt;
&lt;li&gt;遍历所有的边 \(u-v\)，如果 \(u\) 和 \(v\) 不在同一个连通块，就分别用 \(u\) 和 \(v\) 去更新它们所在连通块的最小出边。&lt;/li&gt;
&lt;li&gt;将每个连通块的最小出边加入 MST 的边集。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;由于每次连通块数量减半，所以时间复杂度 \(\Theta(m\log n)\)。&lt;/p&gt;</description></item></channel></rss>