当前位置: 首页 > news >正文

Kruskal与Prim:最小生成树双雄对决

一、上期回顾

掌握 Floyd 多源最短路算法,三层循环实现任意两点间最短路径,适配小规模图。 今天学习最小生成树 (MST),在连通图中选出边权和最小的连通子图,覆盖所有顶点且无环。

二、最小生成树基础概念

  1. 定义:给定连通无向带权图,选取 n-1 条边,连接全部 n 个顶点,且所有边权之和最小,该子树即为最小生成树。
  2. 核心性质
    • 包含图中所有顶点
    • 恰好顶点数-1条边,无回路
    • 总边权和全局最小
  3. 适用场景:城市修路、网络布线、管道铺设、集群组网等求最小成本问题。
  4. 主流两种实现:Kruskal 克鲁斯卡尔Prim 普里姆

三、算法一:Kruskal 克鲁斯卡尔算法

1. 核心思想(贪心 + 并查集)

  1. 将所有边按权值从小到大排序
  2. 依次遍历每条边,用并查集判断两个顶点是否连通
  3. 不连通则选中这条边,合并两个集合;连通则跳过(避免成环)
  4. 选够n-1条边即可结束

2. 完整代码模板

#include <iostream> #include <vector> #include <algorithm> using namespace std; const int N = 1005; // 边结构体:起点u、终点v、权值w struct Edge { int u, v, w; bool operator<(const Edge& e) const { return w < e.w; // 按权值升序排序 } }; vector<Edge> edges; int parent[N]; // 并查集父节点数组 int n, m; // n顶点数,m边数 // 并查集初始化 void init() { for(int i = 1; i <= n; ++i) parent[i] = i; } // 查找+路径压缩 int find(int x) { if(parent[x] != x) parent[x] = find(parent[x]); return parent[x]; } // Kruskal 算法,返回最小生成树总权值 int kruskal() { init(); sort(edges.begin(), edges.end()); // 边排序 int sum = 0; // 总权值 int cnt = 0; // 已选边数 for(auto& e : edges) { int fu = find(e.u); int fv = find(e.v); if(fu != fv) { parent[fv] = fu; sum += e.w; cnt++; if(cnt == n - 1) // 选够n-1条边,提前退出 break; } } // 未选够边数,说明图不连通,无生成树 if(cnt < n - 1) return -1; return sum; } int main() { cin >> n >> m; edges.resize(m); for(int i = 0; i < m; ++i) { cin >> edges[i].u >> edges[i].v >> edges[i].w; } int res = kruskal(); if(res == -1) cout << "图不连通,无法生成最小生成树" << endl; else cout << "最小生成树总权值:" << res << endl; return 0; }

3. 特点与复杂度

  • 复杂度:\(O(m\log m)\),主要耗时在边排序
  • 优势:适合边稀疏的图(边数远小于顶点数),代码简洁
  • 依赖:必须配合并查集判断连通性、防环

四、算法二:Prim 普里姆算法

1. 核心思想(贪心 + 邻接矩阵 / 邻接表)

  1. 维护两个集合:已加入生成树的顶点集合、未加入集合
  2. 每次选取连接两个集合、权值最小的边,将对应顶点加入树中
  3. 重复 n-1 次,直到所有顶点加入

2. 邻接矩阵版模板(适合小规模图)

#include <iostream> #include <cstring> #include <climits> using namespace std; const int N = 1005; const int INF = 0x3f3f3f3f; int graph[N][N]; // 邻接矩阵存图 int dist[N]; // 未选点到生成树的最短距离 bool vis[N]; // 标记是否已加入生成树 int n, m; int prim() { memset(vis, false, sizeof(vis)); // 初始化距离数组 for(int i = 1; i <= n; ++i) dist[i] = graph[1][i]; vis[1] = true; // 从1号顶点开始 int sum = 0; for(int i = 1; i < n; ++i) // 还需选n-1个点 { // 找距离最小的未访问点 int minVal = INF; int pos = -1; for(int j = 1; j <= n; ++j) { if(!vis[j] && dist[j] < minVal) { minVal = dist[j]; pos = j; } } if(pos == -1) return -1; // 图不连通 sum += minVal; vis[pos] = true; // 更新剩余点到生成树的最短距离 for(int j = 1; j <= n; ++j) { if(!vis[j] && graph[pos][j] < dist[j]) dist[j] = graph[pos][j]; } } return sum; } int main() { // 矩阵初始化 memset(graph, 0x3f, sizeof(graph)); cin >> n >> m; for(int i = 1; i <= n; ++i) graph[i][i] = 0; for(int i = 0; i < m; ++i) { int u, v, w; cin >> u >> v >> w; // 无向图双向赋值,重边取最小值 if(w < graph[u][v]) { graph[u][v] = w; graph[v][u] = w; } } int res = prim(); if(res == -1) cout << "图不连通" << endl; else cout << "最小生成树总权值:" << res << endl; return 0; }

3. 特点与复杂度

  • 基础版复杂度:\(O(n^2)\)
  • 优势:适合顶点少、边稠密的图
  • 优化:可搭配优先队列(堆),优化为 \(O(m\log n)\),思路不变

五、两大算法对比 & 选型口诀

表格

算法核心依赖复杂度适用场景
Kruskal并查集 + 边排序\(O(m\log m)\)稀疏图(边少点多),刷题首选
Prim邻接矩阵 / 堆\(O(n^2)\)稠密图(边多点少)

选型口诀:点少边多用 Prim,点多边少用 Kruskal


六、今日核心总结

  1. 最小生成树:连通全顶点、n-1 条边、总权值最小、无环路。
  2. Kruskal:边排序 + 并查集判连通,稀疏图首选。
  3. Prim:以顶点为核心贪心拓展,稠密图更合适。
  4. 两个算法都基于贪心思想,遇到不连通图直接判定无解。

七、课后练习

  1. 手写 Kruskal 完整代码,结合并查集完成测试
  2. 搭建稠密图,使用 Prim 算法求解最小权值
  3. 区分两种算法的使用场景
http://www.jsqmd.com/news/912775/

相关文章:

  • 明清字画回收,认准丰宝斋!全国上门,专业鉴藏,诚信变现 - 深鉴新闻
  • 别再手动调权重了!用Maya/Blender/Houdini一键导出Morph Targets到UE5的完整避坑指南
  • 手把手教你:如何把Cadence的Pspice库搬到TI版本里(附详细避坑指南)
  • 2026年商家小程序外卖怎么找骑手
  • G-Helper完全指南:如何用轻量工具替代Armoury Crate掌控华硕笔记本
  • 抖音批量下载终极指南:高效免费的去水印解决方案
  • 5分钟掌握文泉驿微米黑:终极轻量级中文字体跨平台安装指南
  • 异步电网连接技术:提升电力系统频率稳定的新方案
  • 基于不同视角及主体特性的现货电力市场决策模型构建【附仿真】
  • 别再暴力刷新了!用ScriptableObject和事件驱动重构Unity背包系统,性能提升实测
  • 从零开始组装电脑:预算规划、硬件安装与调试全攻略
  • 如何快速上手无名杀:免费网页版三国杀的终极体验指南
  • 选型避坑指南:开关电源设计中,如何根据米勒电容Crss挑选合适的MOS管?
  • Raw Accel鼠标加速驱动:Windows玩家的终极鼠标响应优化方案
  • 内网开发环境救星:手把手教你用K3s离线搭建轻量K8s集群(避坑指南)
  • Pythonitertools高级模式
  • Claude市场份额暴涨217%的背后:我们访谈了43家中国企业的CTO(独家一线采购动因白皮书)
  • 如何安全合规地管理微信数据:从PyWxDump项目下架看技术合规边界
  • Arm开发中的SDF文件:创建、使用与问题排查
  • 别让宝贝蒙尘!丰宝斋上门回收老书旧书,唤醒时光记忆 - 深鉴新闻
  • Windows 版 OpenClaw 一键安装:3 分钟部署,1 句话让 AI 干完一天活
  • 天学网英语听力对孩子有用吗?2026最新实测给你答案
  • HFSS新手必看:别再搞混工程变量和设计变量了(附Optimetrics实战技巧)
  • 随机梯度下降:从机器学习算法到对抗信息过载的行动心法
  • 计及磁滞效应的变压器低频电磁暂态模型及其在铁磁谐振中的应用方案【附仿真】
  • R语言ggrcs包2.9新功能:singlercs函数保姆级教程,5分钟搞定一张漂亮的限制立方样条图
  • Lindy销售自动化方案实施全周期拆解:从0到1部署、7天见效、90天规模化复制
  • 2026年 高速钢源头厂家最新推荐榜单:W18Cr4V/W6Mo5Cr4V2/W2Mo9Cr4VCo8等高性能模具钢材品牌实力解析与选购指南 - 品牌企业推荐师(官方)
  • 从页、锁、索引、事务理解 MySQL 更新与并发
  • 3分钟掌握Angry IP Scanner:免费网络扫描终极指南