MST性质理解
设图的总结点为
V
,以落在生成树上的结点集为U
,那么尚未落在生成树上的结点集为V - U
。
最小生成树最小边权选择:从U
到V-U
的连通边选择最短的边。
prim算法思路
选择:MST性质。
加入:将选择的最短边的结点加入到生成树集中。
更新:将加入的结点去更新他到尚未落在生成树上的结点集合。
选择
// dis为两个点的边权,vis判断该点是否在生成树集合中
int t = -1;
for (int j = 1; j <= n; j++)
{
if (!vis[j] && (t == -1 || dis[t] > dis[j])) t = j;
// 选择生成树到尚未落在生成树上的结点集合的最短距离
}
加入
vis[t] = true; // 标记该点是生成树的一点
更新
// t为加入生成树的结点
// g[t][j] 表示t到j的距离
for (int j = 1; j <= n; j++) dis[j] = min(dis[j], g[t][j]);
// t去更新尚未落在生成树上的结点集合的距离
总代码
int prim()
{
memset(dis, 0x3f, sizeof dis); // 初始化为无穷
int res = 0; // 记录最小生成树的权值
for (int i = 0; i < n; i++)
{
int t = -1;
for (int j = 1; j <= n; j++)
{
if (!vis[j] && (t == -1 || dis[t] > dis[j])) t = j; // 选择生成树到集合的最短距离
}
if (i && dis[t] == INF) return INF; // i = 0时各边还没更新,都为无穷
// i != 0时若存在的最小边为无穷,证明生成树到不了集合,也就不存在生成树
if (i) res += dis[t]; // 记录最小生成树的权值
vis[t] = true; // 标记该点是生成树的一点
for (int j = 1; j <= n; j++) dis[j] = min(dis[j], g[t][j]); // 更新t到集合的距离
}
return res;
}