最小生成树
最小生成树 - OI Wiki (oi-wiki.org)
例题:P3366 【模板】最小生成树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
kruskal算法#
克鲁斯卡尔(Kruskal)算法是一种用于在加权图中寻找最小生成树的算法。它的工作原理是按照边的权重顺序(从小到大)检查每条边,如果加入这条边不会形成环(用[[并查集]]判断),则将其加入到最小生成树中,直到加入了足够的边为止(对于一个含有(n)个顶点的图,最小生成树将包含(n-1)条边)。
克鲁斯卡尔(Kruskal)算法的时间复杂度主要取决于两个部分:边的排序以及并查集操作。
边的排序:克鲁斯卡尔算法首先需要对图中的所有边按权重进行排序。对于包含(E)条边的图,这一步的时间复杂度是(O(E\log E))。
并查集操作:算法接下来对每条边执行并查集的查找和合并操作,以确定是否添加该边到最小生成树中。在最坏情况下,这些操作的时间复杂度为(O(E\log V)),其中(V)是顶点的数量。然而,使用路径压缩和按秩合并的优化后,并查集操作的平均时间复杂度可以接近(O(1)),因此整个并查集操作的时间复杂度可以认为是(O(E))。
综上所述,克鲁斯卡尔算法的总时间复杂度是(O(ElogE+E)=O(ElogE))。因为在大多数情况下,(E)远大于(V),并且对于稠密图来说,(E)接近于(V2),所以排序的时间复杂度占主导。
优化方法#
更快的排序算法:尽管标准的排序算法(如快速排序、归并排序)的时间复杂度已经是(O(E\log E)),但在特定情况下可以考虑使用基数排序等线性时间复杂度的排序算法,特别是当边权重的范围较小且已知时。
并查集优化:虽然并查集操作的时间复杂度已经很低,但仍然可以通过两种主要技术进一步优化:
- 路径压缩(Path Compression):在执行查找操作时,将查找路径上的每个节点都直接连接到根节点,这样可以减少后续查找操作的深度。
- 按秩合并(Union by Rank):总是将较小的树连接到较大的树的根上,这样可以避免树变得过深,从而优化合并操作的时间复杂度。
减少不必要的操作:在实际实现中,可以通过维护一些额外的数据结构来避免对某些边进行不必要的操作。例如,如果已知某个顶点属于当前最小生成树的连通分量中,那么连接这个顶点和其他属于同一连通分量的顶点的边就不需要考虑。
通过这些优化,克鲁斯卡尔算法的性能可以在实际应用中得到显著提升,尤其是在处理大规模图数据时。
代码实现#
以下是实现克鲁斯卡尔算法的C++代码,包括并查集的实现来帮助检测环:
这段代码首先定义了图的结构,包括顶点、边以及边的权重。然后,它使用并查集数据结构来维护集合的信息,这对于检测加入边时是否会形成环是必要的。在主函数中,我们创建了一个图的实例,添加了一些边,然后调用KruskalMST
函数来找到最小生成树并打印结果。
prim算法#
该算法的基本思想是从一个结点开始,不断加点,每次要选择距离最小的一个结点,以及用新的边更新其他结点的距离。
使用[[STL#优先队列|优先队列]]的二叉堆优化的时间复杂度O((n+m)logn)