prim算法求最小生成树

prim算法求最小生成树

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 501, INF = 0x3f3f3f3f;
int d[N], g[N][N];
int n, m;
bool st[N];

int prim()
{
    memset(d, 0x3f, sizeof d);
    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 || d[t] > d[j]))
                t = j;
        
        if(i && d[t] == INF) return INF;
        if(i) res += d[t];
        st[t] = true;
        for(int j = 1;j <= n;j++)
            d[j] = min(d[j], g[t][j]);//注意这里与Dijkstra区别d[t] + d[t][j]
        
    }
    return res;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    memset(g, 0x3f, sizeof g);
    
    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b] = g[b][a] = min(g[a][b], c);
    }
    int t = prim();
    if(t == INF) puts("impossible");
    else cout<<t<<endl;
}

prime算法和Dijkstra算法求最小距离非常相似。

一开始d[i]全都被赋值为+oo

要找n个点,那么就要循环n次

for  i  0 - n

找到集合外距离最近的点,用新的距离最近的点t来更新其他点到集合的最短距离(Dijkstra这里是更新到起点的距离),st[t] = true;加入到集合当中来。

必须要先累加再更新,如果有负权自环的话,就会再次更新自己 从而加入进来,先累加再更新下一次判断的话因为st[j] = true就不会再更新了。

模拟一遍:i = 0, t = 1, d[1] = oo, 但是不会加入最小生成树的res里面来,因为只有i>0 时,res += d[t]。d[2] = 1, d[3] = 2, d[4] = 3。

接着会用连接的最小距离2来更新其他点。注意是到集合的距离,所以也只是min(d[t], g[t][j]), 而Dijkstra是min(d[t], d[t] + g[t][j]);

posted @ 2020-04-16 17:16  龙雪可可  阅读(228)  评论(0编辑  收藏  举报
****************************************** 页脚Html代码 ******************************************