最小生成树算法之prim算法

本文详细介绍了Prim算法用于寻找图的最小生成树的过程。通过逐步解析,展示了如何从一个顶点出发,迭代地选择与当前生成树连接且权重最小的边,最终形成最小生成树。文章还提供了完整的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

prim算法从找点开始的算法,对于一个图如下:


解释:dist[]为每个点到生成树的最小距离,最开始时候每个点到生成树的最小距离为INF(无穷大),邻接矩阵g[][]来存储图的边数据,不相邻的边距离为INF,每个点到自己的距离为0,visited[]数组来标记每个点是否被访问了

1、刚开始时,最小生成树为空,若取顶点1位源点,则把顶点1加入到生成树中去,设置visited数组visited[1] = 1,初始化每个点到树的最小距离,此时生成树为{1,}

2、进入循环,更新dist[]数组,由于dist[3] = 1,是离树最近的点所以顶点3加入到树中,visited[3] =1 ,生成树:{1,3}

对于加入树中的顶点v,找到v的邻接点,更新dist[]数组

3、重复步骤2,找到此时离树最近的点4,加入到树中,并每次更新dist数组

4、直到所有点 都被访问过了,退出循环,打印最小生成树的长度。若退出循环后还有dist[i] = INF,说明还有点到树的距离为无穷大,说明此图不为联通图,输出"此图不联通"


示例代码:

#include<iostream>
#include<windows.h>
#define MAX 101
#define INF 99999999
using namespace std;
int g[MAX][MAX];
int visited[MAX];
int dist[MAX];
void prim(int s,int n)
{
    int i,j,pos,minn;
    visited[s] = 1;  //将源点表示为已访问 
    pos = s;
    int ans = 0;
    for(i = 1; i <= n; i++) //dist[i]表示点i到最小生成树距离,dist[i] = 0,说明已经加入到最小生成树中了 
    {
        dist[i] = g[s][i];
    }
    while(1)
    {
        minn = INF;
        int done = 0;
        for(j = 1; j <= n; j++) // 从未收录的点中找到距离树最短的顶点 
        {
            if(visited[j] == 0 && dist[j] < minn)
            {
                minn = dist[j];
                pos = j;
                done = 1;
            }
        }
        if(!done)  //所有点都访问过了 跳出循环 
        {
            for(j = 1; j <= n; j++)
            {
                if(dist[j] == INF)
                {
                    cout<<"图不联通"<<endl;
                    return;
                }
            }
            cout<<ans<<endl; 
            break;
        }
        visited[pos] = 1;
        ans += minn;
        //  对于新收录点的每个邻接点,更新每个点到树的距离 
        for(j = 1; j <= n; j++)
        {
            if(visited[j] == 0 && g[pos][j] < dist[j])
            {
                dist[j] = g[pos][j];
            }
        } 
    }   
}

int main()
{
    int n,m,i,j;
    cin>>n>>m;
    for(i = 1; i <= n; i++)  //将所有不同点的距离初始化为无穷大 
    {
        dist[i] = INF;
        for(j = 1; j <= n; j++)
        {
            if(i == j)
            {
                g[i][j] = 0; // 点到自己的距离为0 
            }else
            {
                g[i][j] = INF;        
            }
        }
    }
    for(i = 1; i <= m; i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b] = g[b][a] = c;
    }
    prim(1,n);
    system("pause"); 
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值