最小生成树(Prim算法)

Prim算法的核心思想是"贪心" ,首先最小生成树是一个带权的无向图(最小生成树: n个顶点有n-1条边)。构建最小生成树就是要在带权边上选择最小权的边。首先置S = {1},然后只要S是V的真子集,就做如下贪心选择。选取满足条件i属于S,j属于V-S。且g.arac[i][j]最小的边 。并将符合条件的j顶点添加到S中。直到S = V为止。此过程选取到的边则为构成最小生成树的边。

最小生成树的目的是为了把所有点包进这个网络中,并且网络中的边最短。常用算法有Prim,Kruskal算法。注意与単源最短路径区分。单源最短路径的目的是从一个源节点想方设法找到一条到目的节点的路径。常用算法有:Dijkstra算法。

最小生成树是整体来分析,而单源最短路径是单条路径来分析的。

代码:

Prim算法:

void Prim(graph &g){
     int min_cost = 0;
     int lowcost[NUM];      //当前最短距离
     int closest[NUM];     //顶点的相邻顶点(closest[i]则为i的邻接点)
     int  s[NUM];         //标志访问节点
     for(int i = 1;i<=g.v;i++){
        closest[i] = 1;              //初始置各顶点得邻接点为1
        lowcost[i] = g.arac[1][i];   //初始置各顶点的最短距离为1到顶点的距离
        s[i] = 0;
     }
     for(int i = 1;i<g.v;i++){
       int min = INIT;              //min初始化无穷大 
       int j = 1;
       for(int k = 2;k<=g.v;k++){
           if(lowcost[k]<min&&!s[k]){    //找出与源点相连,且权值最小的顶点 
                min = lowcost[k];  j = k;
           }
           else{
             ;
           }
       }
       min_cost+=min;    
       cout<<closest[j]<<"->"<<j<<endl;     //输出符合最小生成树的顶点 
       s[j] = 1;                           //已访问顶点置1
       for(int t = 2;t<=g.v;t++){
          if(g.arac[j][t]<lowcost[t]&&!s[t]){  //从新添加的顶点j出发,将与j相邻的顶点间的权值
                                              //与上一顶点的相邻顶点间的权值进行比较。选出最小权值和相应顶点.   
            lowcost[t] = g.arac[j][t];
            closest[t] = j;
          }
          else{
            ;
          }
       }
     }
     cout<<"最小生成树得最短路径为:"<<min_cost<<endl;
}

完整代码:

 /**
  @ 最小生成树-Prim算法
*/
#include<iostream>
#include<algorithm>
#include<cstdlib>
#define INIT 63355
#define NUM  20
using namespace std;
typedef int Elemtype;
typedef struct Tnode{
    Elemtype vex[NUM];
    int  arac[NUM][NUM];
    int v,e;
}graph;
void Init_Graph(graph &g){
   for(int i = 1;i<=g.v;i++){
     for(int j = 1;j<=g.v;j++){
        g.arac[i][j] = INIT;
     }
   }
}
void Create_Graph(graph &g){
     cout<<"输入顶点,边数目:"<<endl;
     cin>>g.v>>g.e;
     Init_Graph(g);
     cout<<"输入顶点信息:"<<endl;
     for(int i = 1;i<=g.v;i++){
          cin>>g.vex[i];
     }
     cout<<"输入顶点间下标和权值:"<<endl;
     int k,t,w;
     for(int i = 1;i<=g.e;i++){
        cin>>k>>t>>w;
        g.arac[k][t] = w;
        g.arac[t][k] = g.arac[k][t];
     }
}
void Prim(graph &g){
     int min_cost = 0;
     int lowcost[NUM];      //当前最短距离
     int closest[NUM];     //顶点的相邻顶点(closest[i]则为i的邻接点)
     int  s[NUM];         //标志访问节点
     for(int i = 1;i<=g.v;i++){
        closest[i] = 1;              //初始置各顶点得邻接点为1
        lowcost[i] = g.arac[1][i];   //初始置各顶点的最短距离为1到顶点的距离
        s[i] = 0;
     }
     for(int i = 1;i<g.v;i++){
       int min = INIT;              //min初始化无穷大
       int j = 1;
       for(int k = 2;k<=g.v;k++){
           if(lowcost[k]<min&&!s[k]){    //找出与源点相连,且权值最小的顶点
                min = lowcost[k];  j = k;
           }
           else{
             ;
           }
       }
       min_cost+=min;
       cout<<closest[j]<<"->"<<j<<endl;     //输出符合最小生成树的顶点
       s[j] = 1;                           //已访问顶点置1
       for(int t = 2;t<=g.v;t++){
          if(g.arac[j][t]<lowcost[t]&&!s[t]){  //从新添加的顶点j出发,将与j相邻的顶点间的权值
                                              //与上一顶点的相邻顶点间的权值进行比较。选出最小权值和相应顶点.
            lowcost[t] = g.arac[j][t];
            closest[t] = j;
          }
        }
     }
     cout<<"最小生成树得最短路径为:"<<min_cost<<endl;
}
int main(){
       graph g;
       Create_Graph(g);
       cout<<"最小生成树的构建路径为:"<<endl;
       Prim(g);
  return 0;
}
/**
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 5 6
3 6 4
4 6 2
5 6 6
*/

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值