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;
}