最小生成树之prim算法

最小生成树之prim算法

  最小生成树的概念在上一篇文章中已经叙述了,在这里主要再叙述一种解决最小生成树的算法--prim算法。

  他其实和kruskal算法是互补的,一个从边出发,另一个从点出发寻找最小的总权值。prim算法是从点入手,一开始随机选一个点,找出该点连接的其他所有点中最短的路径,然后把这条边的另一个点加入集合。当集合中的点大于等于2的时候,我们每次都要找出这个集合中与其他不在集合里的点连接的最短的那条边,然后再把这条边的不在集合里的那个点加入集合,就这样一直循环下去,知道把所有的点都加入到这个集合为止。这样每次记录边的权值,最后就是我们要找的答案。

  为了更容易理解,还是以讲解kruskal算法的题目作为例题,示例代码如下(必要的解释有相应注释说明):

  

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;
#define INF 0x3f3f3f3f

int n,m;
int map[105][105],low[105];//low数组表示整个集合对没有在集合的点的最小距离
bool vis[105];//用来表示第i个点是否被用过

void prim()
{
   int pos,sum=0,MIN;

   pos=1;//表示取第一个点作为集合里的第一个点,以这个点为原始点开始向集合里加点
   vis[1]=1;

   for(int i=1;i<=n;i++)
   {
      low[i]=map[pos][i];
   }
   //再循环n-1次就行了,每一次都加入一个点
   for(int i=1;i<n;i++)
   {
       MIN=INF;
       for(int j=1;j<=n;j++)
       {
           if(!vis[j]&&(low[j]!=-1)&&MIN>low[j])
           {
               pos=j;MIN=low[j];
           }
       }

       sum+=low[pos];
       vis[pos]=1;

       for(int j=1;j<=n;j++)//更新最小值
       {
           if(!vis[j]&&low[j]>map[pos][j]&&map[pos][j]!=-1&&low[j]!=-1)
               low[j]=map[pos][j];
       }
   }

   printf("%d\n",sum);
}

int main()
{
//    freopen("s","r",stdin);

    while(scanf("%d",&n)!=EOF)
    {
        memset(vis,0,sizeof(vis));
        memset(map,-1,sizeof(map));

        if(!n) {break;}

        m=n*(n-1)/2;

        for(int i=1;i<=m;i++)
        {
            int x1,x2,dis;
            scanf("%d%d%d",&x1,&x2,&dis);
            //表示x1和x2之间的边是多长
            map[x1][x2]=dis;
            map[x2][x1]=dis;
        }

        prim();
    }
    return 0;
}

  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值