Prim算法总结

Prim算法模版

//需包含头文件<vector>
//需要用到结构体
//需定义const常量INF为无穷大(const int INF = 0xffffff)
//需建立以动态数组为元素的一维数组此处为w[]
//需定义bool类型的数组intree[]来记录某点是否已加入所求点中
//需对数组mindist[]进行初始化,使mindist[]中每个元素都为无穷大
int Prim(int s)                                                  //s 为起点
{                                                                 
    int vex,addNode,tempMin;                                     //vex 为所求根节点的第一次分支节点位置
                                                                 //addNode 为满足条件要加入目标节点结合的点的位置
                                                                 //tempMin 它负责记录所遍历的所有所求根节点的第一次分支节点的最小权值(对每个第一次分支节点的权值进行比较,取最小)
    intree[s] = true;
    for(unsigned int i = 0;i < w[s].size();i++)                  //把起点当作一个根节点,遍历起点的所有的第一次分支节点
    {
        vex = w[s][i].vex;                                       //记录起点的每一个第一次分支节点位置
        mindist[vex] = w[s][i].weight;                           //记录起点的每一个第一次分支节点的到起点的权值(mindist[]数组记录的是未加入所求点集的所有点到所求点集里的所有点的最小权值)
    }
    for(int nodeNum = 1;nodeNum <= N-1;nodeNum++)                //对余下的所有点进行遍历
    {
        tempMin = INF;                                           
        for(int i = 1;i <= N;i++)                                //对所有点进行遍历
        {                                                        
            if(intree[i] == false && mindist[i] < tempMin)       //判断第i点是否已经在所求点集里并且判断第i点到所求点集的权值是否为最小
            {
                tempMin = mindist[i];                            //更新最小权值
                addNode = i;                                     //记录到所求点集最小权值的点的位置 
            }
        }                                                               
        intree[addNode] = true;                                  //将具有到所求点集的最小权值的点放入所求点集
        ans += tempMin;                                          //对求得的最小权值相加
        for(unsigned int i = 0;i < w[addNode].size();i++)        //对新加入所求点集的点的第一次分支节点进行遍历
        {                                    
            vex = w[addNode][i].vex;                             //记录新加入所求点集的点的第一次分支节点的位置
            if(intree[vex] == false && w[addNode][i].weight < mindist[vex])  //对未加入所求点集的点到所求点集的权值进行更新,使未加入所求点集的点到所求点集的权值最小
                mindist[vex] = w[addNode][i].weight;
        }
    }
    return ans;                                                  //返回最小权值之和
}                                                                //所求点集为最小生成树

Prim算法作用:

例:修N个村庄的路,每个村庄间的路都有不同的经费,要修N-1条路使得经费最小,求最小经费

例题HDU_1233:

#include <cstdio>
#include <vector>

using namespace std;


struct Weight
{
    int vex,weight;
    Weight(int vex = 0,int weight = 0):vex(vex),weight(weight){}
};



const int max_num_weight = 5005;
const int max_country = 105;
const int INF = 0xffffff;



int N;
int ans;
int rank[max_country];
int mindist[max_country];
bool intree[max_country];
vector<Weight> w[max_country];




void Init()
{
    ans = 0;
    for(int i = 1;i <= N;i++)
    {
        w[i].clear();
        intree[i] = false;
        mindist[i] = INF;
    }
    return ;
}
int Prim(int s)
{
    int vex,addNode,tempMin;
    intree[s] = true;
    for(unsigned int i = 0;i < w[s].size();i++)
    {
        vex = w[s][i].vex;
        mindist[vex] = w[s][i].weight;
    }
    for(int nodeNum = 1;nodeNum <= N-1;nodeNum++)
    {
        tempMin = INF;
        for(int i = 1;i <= N;i++)
        {
            if(intree[i] == false && mindist[i] < tempMin)
            {
                tempMin = mindist[i];
                addNode = i;
            }
        }
        intree[addNode] = true;
        ans += tempMin;
        for(unsigned int i = 0;i < w[addNode].size();i++)
        {
            vex = w[addNode][i].vex;
            if(intree[vex] == false && w[addNode][i].weight < mindist[vex])
                mindist[vex] = w[addNode][i].weight;
        }
    }
    return ans;
}



int main()
{
    while(scanf("%d",&N)&&N)
    {
        Init();
        int v1,v2,weight;
        for(int i = 0;i < N*(N-1)/2;i++)
        {
            scanf("%d%d%d",&v1,&v2,&weight);
            w[v1].push_back(Weight(v2,weight));
            w[v2].push_back(Weight(v1,weight));
        }
        Prim(1);
        printf("%d\n",ans);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值