Prim算法核心是贪心策略:从任一顶点出发,维护key[](到生成树最短边权)和mstSet[](是否已入树),每次选key最小未访问顶点并松弛邻接点;邻接矩阵实现需初始化key全为INT_MAX、起点为0,更新时须同时判断顶点未访问且边存在。

Prim算法的核心逻辑是什么
Prim算法从任意一个顶点出发,每次选择与当前生成树相连的、权值最小的边,把对应新顶点加入树中。关键不是“选边”,而是维护一个key[]数组(记录每个顶点到当前生成树的最短边权)和一个mstSet[]布尔数组(标记是否已入树)。它本质上是贪心 + 类Dijkstra的松弛过程。
用邻接矩阵实现Prim时要注意什么
邻接矩阵适合稠密图,代码简洁但时间复杂度为 O(V²)。容易出错的地方集中在三处:
-
key[]初始化必须全为INT_MAX,但起始点要设为0,否则第一个顶点无法被选中 - 更新
key[v]时,必须同时检查!mstSet[v]和graph[u][v] != 0(或),否则会误更新已加入的点或不存在的边 - 找最小
key[u]的循环里,必须跳过已加入的点(即mstSet[u]为true的情况),否则会重复选点
#include#include using namespace std; void primMST(int graph[][5], int V) { int parent[V]; int key[V]; bool mstSet[V];
for (int i = 0; i zuojiankuohaophpcn V; i++) { key[i] = INT_MAX; mstSet[i] = false; } key[0] = 0; parent[0] = -1; for (int count = 0; count zuojiankuohaophpcn V - 1; count++) { int u = -1; for (int v = 0; v zuojiankuohaophpcn V; v++) { if (!mstSet[v] && (u == -1 || key[v] zuojiankuohaophpcn key[u])) u = v; } mstSet[u] = true; for (int v = 0; v zuojiankuohaophpcn V; v++) { if (graph[u][v] && !mstSet[v] && graph[u][v] zuojiankuohaophpcn key[v]) { parent[v] = u; key[v] = graph[u][v]; } } } for (int i = 1; i zuojiankuohaophpcn V; i++) cout zuojiankuohaophpcnzuojiankuohaophpcn parent[i] zuojiankuohaophpcnzuojiankuohaophpcn " - " zuojiankuohaophpcnzuojiankuohaophpcn i zuojiankuohaophpcnzuojiankuohaophpcn " \t" zuojiankuohaophpcnzuojiankuohaophpcn graph[parent[i]][i] zuojiankuohaophpcnzuojiankuohaophpcn endl;}
用邻接表 + 优先队列优化到
O(E log V)稀疏图必须换邻接表+最小堆(
priority_queue),否则超时。C++标准库的priority_queue默认是最大堆,得用greater或取负;更稳妥的是自定义比较器。还要注意:堆里可能存着已失效的旧> key值,所以每次pop后必须检查mstSet[v],跳过已处理的点。立即学习“C++免费学习笔记(深入)”;
- 不要直接 push 新权值就完事,要 push
{weight, vertex}对- 更新
key[v]后必须重新 push,不能修改堆中已有元素- 图用
vector存:外层索引是起点,内层是>> {终点, 权值}常见报错和调试线索
运行时崩溃或结果错误,八成出在边界上:
- 输入邻接矩阵时行列数没对齐,比如传了
graph[5][4]却用V=5遍历第5行 → 越界访问- 图不连通时,
key[v]保持INT_MAX,最后输出边权为大负数(整数溢出)→ 应提前检查是否存在key[v] == INT_MAX且!mstSet[v]- 使用
priority_queue时忘了加!mstSet[v]判断,导致同一顶点被多次加入生成树最小生成树不一定唯一,只要总权值最小、边数等于
V-1、无环,就是正确解。验证时别只盯边顺序,重点看连通性和权值和。










