Prim算法

思想:选定一个顶点,向外搜索与其他顶点相连的边的最小权值,将搜索到的顶点加入初始顶点集合,构成生成树,利用lowcost数组存储最小生成树到其他未加入生成树的点的距离,再次遍历,重复上述,直到所有点都被找到
偷了我们数据结构老师的一张图,以此来进行详解,我们以一个二维数组map来存储各点之间的距离,随意选择一个顶点出发遍历(最小生成树是为了求将图中所有顶点联通的最小距离,所以总路径长度即结果只有一个,所以节点是任选的),废话不多说,上代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define MAX 1<<20
#define M 1005
#include<iostream>
using namespace std;
int lowcost[M];//当前生成树u的集合到其他各顶点的边最短的集合
//lowcost初始为出发点到其他点的距离,不断更新为二叉树
int vis[M];//标记节点是否进入生成树,1为进入,0为无
int N;//顶点个数
int e;//边的个数
int map[M][M];//基础输入
void prim(int N,int v)//v为出发点
{
    for(int i=0; i<N; i++)
    {

        lowcost[i]=map[v][i];//记录起点v距离其他点的距离
        if(!lowcost[i])
        {
            lowcost[i]=MAX;
        }
        vis[i]=0;//初始化所有的点都没有进入二叉树
    }
    vis[v]=1;//很明显v进入二叉树,所以进行标记
    int sum=0;//记录最短路长度,最短路数据存在lowlost数组里
    int k;
    int min;
    int num;
    for(int i=0; i<e; i++)
    {
        num=0;
        min=MAX;//初始为最大值
        for(int j=0; j<N; j++)
        {
            if(vis[j]==0&&lowcost[j]<min&&lowcost[j]>0)
            {
                min=lowcost[j];
                k=j;
                num++;
            }
        }//不断循环,知道发现与v相连的最小边,计入最短路
        if(num)
        {
            sum+=min;
            cout<<v<<"------"<<k<<"-------"<<min<<endl;
        }
        v=k;//此时将v更新为k,查找k的最近边
        vis[k]=1;
        //开始更新lowcost的数值,如果vis[j]==0;
        //说明已经在此之前已经两个顶点已经联通,
        //所以只遍历与出发点同属并查集但并未初始相连的点
        for(int j=0; j<N; j++)
        {
            if(vis[j]==0&&map[v][j]<lowcost[j]&&map[v][j]>0)//此处v已经更新为新的节点,所以将其关联点距离与出发点距离各顶点做对比
            {
                lowcost[j]=map[v][j];
            }
        }
    }
    printf("%d\n",sum);
}
int main()
{
    int zz,ww;//zz为数量,ww为路数
    int u,v,cost;
    int p;
    while(scanf("%d%d",&zz,&ww)!=EOF)
    {
        memset(lowcost,0,sizeof(lowcost));
        memset(vis,0,sizeof(vis));
        N=zz;
        e=ww;
        for(int i=0; i<ww; i++)
        {
            scanf("%d%d%d",&u,&v,&cost);
            map[u][v]=cost;
            map[v][u]=cost;
        }
        scanf("%d",&p);
        prim(N,p);
    }
    return 0;
}
结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值