最小生成树之普里姆(prime)算法

参考:

(48条消息) 最小生成树详解(模板 + 例题)_潘小蓝的博客-CSDN博客_最小生成树例题详解

思路:

把点和边的值都赋为无穷大

1.有n个点,寻找n

2.寻找最小的点,要求:未连通viss[j]=0,最小

3.如果找到最小点的dist不为无穷大

4.存储dist,标记当前点(vis[cur]=1

5.改变与当前最小点连通的点kdist的值(k也未被连通过)

6.寻找n次后返回sum

7.若sum不为无穷大,则输出

 

复制代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1000;
int dist[maxn];//点的最小值 
int vis[maxn];//标记是否已经求完了 
int a[maxn][maxn];//路径的权值,有两个部分:u到v,v到u都为w 
int m,n,u,v,w;
long long sum=0;
int prime(int pos)
{
    dist[pos]=0;//pos=1(第一个节点)与自己的距离为0 
    for(int i=1;i<=n;i++)//n个节点,判断n次 
    {
        int cur=-1;
        for(int j=1;j<=n;j++)//寻找最小结点,绝对与当前的那个点连通 
                             // 因为:一开始每个点都是无穷大,改变dist数组的元素只与下面的k循环有关 
        {
            if(!vis[j]&&(cur==-1||dist[j]<dist[cur]))
            cur=j;
        }
        //是否为无穷大 
        if(dist[cur]>=INF) return INF;
        sum+=dist[cur];
        //把当前的点标记为1 
        vis[cur]=1;
        for(int k=1;k<=n;k++)//更新与当前点相邻的点k的dist 
        {
            if(!vis[k])//未被归入树中 
            {
                dist[k]=min(dist[k],a[cur][k]);//必须与cur连通,不然a[cur][k]的值为无穷大 
            }
        }
    }
    return sum;
}
int main()
{
    cin>>n>>m;
    //一开始把路径和点的值都赋为无穷大 
    memset(a,0x3f,sizeof(a));
    memset(dist,0x3f,sizeof(dist));
    for(int i=1;i<=m;i++)
    {
        cin>>u>>v>>w;
        //给路径赋值,两个方面a[u][v],a[v][u],全部为w 
        a[u][v]=min(a[u][v],w);
        a[v][u]=min(a[u][v],w);
    }
    long long value=prime(1);
    //返回的值是否为无穷大 
    if(value>=INF)
    {
        puts("impossible");
    }
    else
    {
        printf("%lld",sum);
    }
    return 0;
}
复制代码

 

 

posted @   格蕾  阅读(412)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示