Prim 算法整体思路
int dist[N], st[N] // 表示该点是否已经成为连通部分的一个点
int dist[1] = 0; // 取起始点为1
for(i : 1 ~ n)
t <- 找出不在连通部分,距离连通部分最近的点
st[t] = true;
更新t点与其他点的dist值
问题1:
如何找出不在集合中的距离集合(最小生成树)最小的点?
int t = -1; // 表示还没找到距离最近的点
for(int j = 1; j <= n; j ++)
if(!st[j] && (t = -1 || dist[t] > dist[j])) // 这里dist[t] > dist[j] 指的是已经更新过的点t!=-1
t = j;
问题2:
最小生成树不存在该如何表示(该图不是连通图)?
if(i && dist[t] == INF) return INF // 将i = 0 的情况排除在外
问题3:
最小生成树的边值该如何进行累加?
if(i) res += dist[t];
问题4:
怎么用t点更新不在集合内的距离?
for(int j = 1; j <= n; j ++)
dist[j] = min(dist[j], g[t][j]);
参考代码
#include <bits/stdc++.h>
using namespace std;
const int N = 510, INF = 0x3f3f3f3f;
int n, m;
int a, b, w;
int g[N][N], dist[N], st[N];
int prim()
{
memset(dist, INF, sizeof dist);
dist[1] = 0;
int res = 0;
for (int i = 0; i < n; i ++)
{
int t = -1;
for (int j = 1; j <= n; j ++)
{
if(!st[j] &&(t == -1 || dist[t] > dist[j])) t = j;
}
st[t] = 1;
if(i && dist[t] == INF) return INF;
if(i) res += dist[t];
for (int j = 1; j <= n; j ++)
{
dist[j] = min(dist[j], g[t][j]);
}
}
return res;
}
int main()
{
memset(g, INF, sizeof g);
cin >> n >> m;
while (m --)
{
cin >> a >> b >> w;
g[a][b] = g[b][a] = min(w, g[a][b]);
}
int t = prim();
if(t == INF) puts("impossible");
else printf("%d", t);
return 0;
}