最小生成树可并行化的 Sollin(Boruvka)算法

news/2025/2/15 11:31:55/文章来源:https://www.cnblogs.com/ofnoname/p/18716557

上期回顾:https://www.cnblogs.com/ofnoname/p/18715203

在前文中,我们剖析了最小生成树(MST)问题中的两大经典算法:

  • Kruskal 以“边权平等”为信条,通过排序与并查集自下而上聚合连通分量;
  • Prim 以“中心辐射”为策略,通过优先队列自上而下扩张领土。

二者虽路径迥异,却殊途同归,均以贪心策略保证全局最优。还有一种不那么为人熟知的 Sollin 算法(又称 Boruvka 算法),它融合了前两者的思想,并在并行计算领域大放异彩,在特定情况下非常有用。

Sollin 算法:分治与并行

Sollin 算法仍然基于贪心,但是他从多个起点开始。想象一场战国时代的争霸赛:初始每一个点都是一代表一个国家,自身是一个连通分量,接下来每个小国(连通分量)各自派出使者,寻找与邻国间成本最低的结盟道路。所有国家同时行动,每一轮合并后形成更大的联盟,直到天下归一。Sollin 算法的核心正是这种分阶段的并行贪心策略

具体步骤

  1. 初始化:每个节点自成一个连通分量。
  2. 并行探索:每一轮迭代下,对每个连通分量,找到其连接外界的最小权重边(类似 Prim 的切割性质)。
  3. 批量合并:将所有找到的最小边加入 MST,合并连通分量。
  4. 循环迭代:重复步骤 2-3,直至只剩一个连通分量。

image

正确性证明

Sollin 的正确性同样基于安全边定理

每个连通分量选择的最小出边,必定属于某个 MST。

归纳法视角

  • 初始状态:每个节点独立,所有边均为安全边候选。
  • 归纳假设:当前已选边集是某个 MST 的子集。
  • 归纳步骤:每轮选择的边均为不同切割的最小边,加入后仍保持 MST 的存在性。

关键观察

  • 若两个连通分量选择彼此之间的同一条边,该边只会被加入一次(去重机制)。
  • 合并操作保证连通分量数量至少减半,确保算法终止。
struct Edge {int u, v, weight, index;
};class Graph {int n, m;vector<Edge> edges;public:Graph(int n, int m) : n(n), m(m) {}void addEdge(int u, int v, int weight, int index) {edges.push_back({u, v, weight, index});}long long boruvka(vector<int>& result) {UnionFind uf(n); // 并查集实现略long long total_weight = 0;int components = n;while (components > 1) {vector<Edge> min_edges(n, {-1, -1, INT_MAX, -1});// 查找每个连通分量的最小边for (const auto& edge : edges) {int root_u = uf.find(edge.u);int root_v = uf.find(edge.v);if (root_u == root_v) continue;if (edge.weight < min_edges[root_u].weight)min_edges[root_u] = edge;if (edge.weight < min_edges[root_v].weight)min_edges[root_v] = edge;}// 收集并处理有效边unordered_set<int> valid_edges;for (int i = 0; i < n; ++i) {if (min_edges[i].index != -1 && !uf.connected(min_edges[i].u, min_edges[i].v)) {valid_edges.insert(min_edges[i].index);}}if (valid_edges.empty()) break;// 合并连通分量并记录结果int added = 0;for (int idx : valid_edges) {const Edge& e = edges[idx];if (uf.unite(e.u, e.v)) {total_weight += e.weight;result.push_back(idx);added++;}}if (added == 0) break;components -= added;}return components == 1 ? total_weight : -1;}
};

时间复杂度

  • 每轮操作成本
    • 寻找每个连通分量的最小边:\(O(|E|)\)(需遍历所有边)。
    • 合并连通分量:使用并查集优化后接近 \(O(|V| \cdot \alpha(|V|))\)
  • 轮数上限:由于每轮连通分量数量至少减半,总轮数为 \(O(\log |V|)\)
  • 总复杂度\(O(|E| \log |V|)\),与二叉堆优化的 Prim 算法相当。

Sollin vs Kruskal

维度 Sollin (Boruvka) Kruskal
核心策略 多连通分量并行找最小边 全局排序 + 单线程并查集
时间复杂度 \(O(|E| \log |V|)\) \(O(|E| \log |E|)\)
空间复杂度 需维护多个连通分量 只需存储并查集和边列表
并行潜力 ✅ 每轮操作天然可并行(如MapReduce) ❌ 排序和并查集依赖全局状态
适用场景 边权分布均匀的图,或需要并行处理 稀疏图(\(|E| \ll |V|^2\)
实现难度 较高(需处理多分量合并与去重) 简单(仅排序与并查集)

在分布式系统中,每轮各连通分量的最小边搜索可分配给不同计算节点,适合超大规模图(如社交网络分析)。据说 Boruvka 算法在 20 世纪 20 年代被用于规划捷克斯洛伐克的电力网络,其分阶段特性契合人工计算流程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/884192.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pip install shutilwhich 安装shutil

(base) C:\Users\Administrator>pip install shutilLooking in indexes: https://mirrors.aliyun.com/pypi/simpleERROR: Could not find a version that satisfies the requirement shutil (from versions: none)ERROR: No matching distribution found for shutil正确 安装…

图片PDF向量化处理的探索与实践

在构建AI本地知识库时,我们不可避免地需要对PDF文件进行处理。PDF文件大致分为两种:扫描的图片文件和非图片文件。对于非图片类型的PDF,可以直接提取文本并进行向量化处理;但对于图片类型的PDF(如扫描件),处理起来就复杂得多。问题背景 图片类型的PDF文件通常存在以下问…

Android ADB 使用笔记

ADB(Android Debug Bridge)是用于与 Android 设备和模拟器交互的命令行工具。通过客户端、服务器和守护进程的协作,提供设备管理、应用安装与卸载、文件操作、系统设置控制等功能。常用命令包括连接设备、安装 APK、截图、录屏、模拟按键、获取设备信息等,是 Android 开发和…

别再误解了!AI 不是软件且不接受反驳!

是的,今天的 AI 是用软件编写的,但如今的实现实际上是一个计算图,它计算的是虚拟神经元网络的行为。软件仅仅是该网络的一个模拟。 让我解释一下。 就像我说的,神经网络 AI 实际上是一组相互连接的虚拟“神经元”。每个神经元或多或少地模拟了人类神经元的行为。这张图数学…

欧拉角和四元数,3D 游戏开发中“旋转”难题的通俗讲解和应用实战

本文深入浅出地介绍了3D游戏开发中常用的旋转工具——欧拉角和四元数。通过生动的例子和代码演示,详细解释了它们的基本概念、应用场景以及如何解决万向锁、插值和计算效率等问题。无论你是初学者还是有经验的开发者,都能从中获得实用的知识和技巧……春节期间,老牛同学学习…

【Go-bug】go引入自建包名报错 package XXX is not in std

引入 这个问题从昨晚学到Package和Module这块的时候就开始折磨我,这里说道:Go语言也有 Public 和 Private 的概念,粒度是包。如果类型/接口/方法/函数/字段的首字母大写,则是 Public 的,对其他 package 可见,如果首字母小写,则是 Private 的,对其他 package 不可见。于…

[AI/前沿展望/综述] AI大模型的技术生态链全景图

序【特别说明】1、本文主要面向对象:开发者、对AI前沿技术感兴趣、基于AI创业的伙伴们 2、本文是对当前AI大模型的技术生态链的【综述】性文章。(文章有点长,预计阅读时长>10min)3、原作者:阿里云开发者(组织机构)(故,极小部分观点有含暗广的嫌疑。但瑕不掩瑜)关键词AI大模…

大语言模型的解码策略与关键优化总结

本文系统性地阐述了大型语言模型(Large Language Models, LLMs)中的解码策略技术原理及其实践应用。通过深入分析各类解码算法的工作机制、性能特征和优化方法,为研究者和工程师提供了全面的技术参考。主要涵盖贪婪解码、束搜索、采样技术等核心解码方法,以及温度参数、惩罚机…

mini-lsm通关笔记Week3Day3

项目地址:https://github.com/skyzh/mini-lsm 个人实现地址:https://gitee.com/cnyuyang/mini-lsm在本章中,您将:在上一章的基础上完成读路径,以支持快照读。 实现事务API,支持快照读。 引擎恢复过程中能正确恢复已提交时间戳。最后,您的引擎将能够为用户提供存储键(key…

软件测试流程——H模型

1、产品开需求澄清会议 2、开发和测试拿到需求 3、分析需求,编写测试计划 4、编写测试用例 5、评审测试用例 6、评审通过,将用例导入用例管理工具 7、搭建环境 8、开发提交项目代码包,达到准入条件 9、测试将项目代码包部署到环境中 10、开始冒烟测试 (冒烟测试通过,则进入…

请求被中止: 未能创建 SSL/TLS 安全通道_微信红包接口_iis_windows

开发微信红包接口过程中出现:请求被中止: 未能创建 SSL/TLS 安全通道。本地调试正常,但是服务器上不行。 通用方法:指定使用的协议tls(https://myssl.com,这里可以测试对应接口服务器支持的协议) 证书导入赋予权限,参考如下文章: 两种方式彻底解决请求被中止- 未能创建…

SpringBoot环境搭建

JDK 在Oracle官网下载JDK11需注册Oracle账户,较麻烦。 在https://jdk.java.net/archive/找到11 GA (build 11+28)下载Windows版本的压缩包解压后将jdk-11文件夹放到合适位置(多个版本可同时存在),IDE可自动检测到该JDK 如果存在问题可能需要进一步配置环境变量,先创建一个…