Prim算法

算法流程:

(1)初始化所有点到已加入点集合的距离为INF。

(2)做n次遍历,每次从未加入集合的点中找到离集合距离最小的点,将该点加入到生成树中。

(3)在每次循环中一旦找到距离最小的点后,使用该点来更新集合外的点到集合的距离。

使用的数据结构:领接矩阵(稠密图)

代码如下:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 510, INF = 0x3f3f3f3f;

int g[N][N];
int dist[N]; // 表示每个点到集合的距离
bool st[N];

int n, m;

int prim()
{
    // 初始化所有距离为INF
    memset(dist, 0x3f, sizeof dist);
    // 迭代N次,找到N个点
    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;
        }
        // 如果不是第一个点,且离集合的距离为INF,则表示该图为非联通图
        if(i && dist[t] ==  INF) return INF;
        //  如果不是第一个点,则改点对应的边加入集合中
        if(i) res += dist[t];
        st[t] = true;
        
        // 更新到集合的距离, 因为加入了一个点,所有需要更新其他点到该点的距离,也就是到集合的距离
        for(int j=1;j<=n;j++)
        {
            dist[j] = min(dist[j], g[t][j]);
        }
        
    }
    return res;
    
}

int main()
{
    cin >> n >> m;
    memset(g, 0x3f, sizeof g);
    
    while(m--)
    {
        int u, v, w;
        cin >> u >> v >> w;
        g[u][v] = g[v][u] = min(g[u][v], w);
    }
    
    int res = prim();
    
    if(res > INF / 2) puts("impossible");
    else cout << res << endl;
    
    return 0;
}

 

posted @ 2022-07-12 11:34  krystalZ2021  阅读(72)  评论(0)    收藏  举报