prim算法

适用情况:稠密图时适用(比如点数 n = 500 边数 m = 10000)

思想:将最小生成树看成是一个集合,最开始这个集合中的元素为0个,然后依次添加不同的点进来

算法步骤:

1. 首先将所有点与集合的距离初始化为无穷大

2. 随便先加入一个点进入到该集合

3. 然后更新其他所有点到该点的距离(即与该集合的距离)

4. 选取距离最近的点加入到该集合(如果最近的点都是正无穷,说明该点没有联通到集合,直接返回)

5. 同以上步骤,将新加入该点附近没有在集合中的点到集合的距离全部更新

6. 继续同上,直到全部点都加入到集合中为止

代码:

#include<iostream>
#include<cstring>
using namespace std;
const int N = 510;
int g[N][N],dist[N];
int res;
bool st[N];
int n,m;

void prim(){
    
    memset(dist,0x3f,sizeof dist);  // 初始化到集合的距离
    dist[1] = 0;
    
    for(int i = 1;i <= n;i ++ ){
        int t = -1;
        for(int j = 1;j <= n;j ++ ){
            if(!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        }
        if(dist[t] == 0x3f3f3f3f){   // 说明没有新的点可以更新,与集合不连通,直接返回
            puts("impossible");
            return;
        }
        st[t] = true;
        res += dist[t];
        for(int j = 1; j <= n;j ++ ){
            dist[j] = min(dist[j],g[t][j]);  // 已经加入集合的元素dist为多少都不影响结果了
        }
    }
    
    cout<<res<<endl;
}


int main(){
    
    memset(g,0x3f,sizeof g);
    
    cin>>n>>m;
    for(int i = 1;i <= m;i ++ ){
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b] = g[b][a] = min(g[a][b],c);  // 这里是无向图,同时加上两条边的距离
    }
    
    prim();
    
    return 0;
}

几个注意点:

1. 该题中存在自环,不能够根据dist[i] 中存在 0x3f3f3f3f 来判断是否能生成最小生成树

(以下代码存在问题,因为在更新边的时候,如果更新的是自己到自己的距离,那么如果没有与集合联通的中存在自环的话,会把自己更新变小,那么就不存在dist == 0x3f3f3f3f 的情况了)

事实上,这道题在把点加入到集合之后,该点dist的距离就不重要了,随便让他怎么更新

    for(int i = 1;i <= n;i ++ ){
        if(dist[i] == 0x3f3f3f3f){
            puts("impossible");
            return;
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值