AcWing 858. Prim算法求最小生成树(稠密图)

Posted MangataTS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing 858. Prim算法求最小生成树(稠密图)相关的知识,希望对你有一定的参考价值。

题目链接

https://www.acwing.com/problem/content/description/860/

思路

prim算法的思想就是,我们维护一个最优集合,然后寻找所有不在集合的点连向集合的最短边,然后将这个点加入集合,并将权值加入总权值中,对于每一个最短边的点,我们用该点更新一下其他点到集合的距离就好了(这里和迪杰斯特拉不太一样,迪杰斯特拉是更新下一个点到源点的距离,而这里是更新没在集合中的点到集合的距离)

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 500+10;

int n,m;
int g[N][N];
int dis[N];
int vis[N];
const int INF = 0x3f3f3f3f;

int prim()
    memset(dis,0x3f,sizeof dis);
    int ans = 0;
    for(int i = 0;i < n; ++i)
        int t = -1;
        for(int j = 1;j <= n; ++j)
            if(!vis[j] && (t == -1 || dis[j] < dis[t])) t = j;
        
        if(i && dis[t] == INF) return INF;//如果不是第一个点并且下一个点的位置为正无穷,说明不联通
        if(i) ans += dis[t];//如果不是第一个点,那么就说明有一条边连向我们的最小生成树集合中
        vis[t] = true;//将当前的t更新为访问
        for(int j = 1;j <= n; ++j) if(!vis[j]) dis[j] = min(dis[j],g[t][j]);//如果不在集合中,那么就选择是否更新
    
    return ans;


int main()
    scanf("%d%d",&n,&m);
    memset(g,0x3f,sizeof g);
    for(int i = 0;i < m; ++i) 
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        g[u][v] = min(g[u][v],w);
        g[v][u] = g[u][v];
    
    int ans = prim();
    if(ans == INF) printf("impossible");
    else printf("%d\\n",ans);
    
    return 0;

以上是关于AcWing 858. Prim算法求最小生成树(稠密图)的主要内容,如果未能解决你的问题,请参考以下文章

最小生成树的prim算法 边的权值为啥不能为负值

最小生成树的prim算法 边的权值为啥不能为负值

Prim算法和Kruskal算法求最小生成树

prim和kruscal算法得到的最小生成树是不是一样

急求KRUSKAL算法求最小生成树过程演示

欧几里德 平面最小生成树算法