【Prim算法】

 Prim算法

  核心思路

从图G<V,E>选取任意一个点为起始点,加入集合S中。在除S外的点集V-S中,找与集合S有最短距离的结点(假设为u),把u作为中介点,优化其他顶点到集合S的最短距离。

(一句话,找结点--->未访问过且使该结点到S距离最短,优化其他点)

伪代码:

int Prim(G,dis[])
{
    初始化
    for(循环n-1次)   //找到权值最小的n-1条边
    {
        for(遍历所有结点)     //找未被访问过的结点u,u到集合S的距离最短(打擂台的方法)
        记u为已访问过
        for(遍历所有结点)    //以u为中介点优化V-S中的结点到S的距离dis[],假设u可达的结点为v
        {  if(v未被访问过&&dis[v]>G[u][v])
            dis[v]=G[u][v];
          }
    }
}

 具体实现的代码:

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=100;
bool visited[MAXN]={false};
class MGraph
{
public:
    MGraph(int a[],int n,int e);
    ~MGraph(){}
    int Prim(int v);//返回最小生成树的所有边的权值之和,即生成树的代价
private :
    int vertexnum,edgenum;
    int edge[MAXN][MAXN];
    int vertex[MAXN];
};
MGraph::MGraph(int a[],int n,int e)
{
    vertexnum=n;
    edgenum=e;
    int p,q,w;
    for(int i=1;i<=n;i++)
        vertex[i]=a[i];
    for(int i=0;i<=n+1;i++)
        for(int j=0;j<=n+1;j++)
            edge[i][j]=INF;//假设所有的点都是不连通的,所以彼此不可达,距离为INF
    for(int i=1;i<=e;i++)
    {
        //cout<<"请输入存在边的两个结点及其权值";
        cin>>p>>q>>w;    
        //注意此处的输入,用于简单图,即无平行边,如果有平行边,原来的边长会被覆盖。
        //所以非简单图可以加个判断语句保留两结点之间最短的边。
        edge[p][q]=edge[q][p]=w;
    }
}
int MGraph::Prim(int v)//假定从v结点开始访问
{
    int dis[vertexnum+2];
    for(int i=1;i<=vertexnum;i++)
        dis[i]=INF;
    for(int i=1;i<=vertexnum;i++)
        dis[i]=edge[v][i];//初始化其他顶点到S集合的距离
    int ans=0;    //统计权值之和
    dis[v]=0;    //!!!起始结点到集合S的距离为0
    visited[v]=true;    //将v结点加入S集合
    for(int k=1;k<vertexnum;k++)    //注意!循环n-1次,找n-1条边
    {
        int MIN=INF,u=-1;
        for(int i=1;i<=vertexnum;i++)
        {
        //找与S集合有最短距离的点u;
         if(visited[i]==false&&dis[i]<MIN)
         {
             MIN=dis[i],u=i;
         }
        }
        //cout<<u<<" ";
        if(u==-1) return -1;//图不连通,不能形成树
        visited[u]=true;//将结点u加入S集合
        ans+=dis[u];
        for(int i=1;i<=vertexnum;i++)
        {
            if(visited[i]==false&&dis[i]>edge[i][u])    //以u为中介点优化其他顶点到S集合之间的距离
                dis[i]=edge[i][u];
        }
    }
    return ans;
}
int main()
{
    int n,e;
    cin>>n>>e;
    int a[n+2];
    for(int i=0;i<=n;i++)
        a[i]=i;
    MGraph Tree(a,n,e);
    int ans=Tree.Prim(1);
    if(ans==-1) cout<<"orz";
    else cout<<ans;
}

总结:

(1)与Dijkstra的区别,在于记录距离的数组dis[]含义不同,Prim是优化未访问的结点Vi 到集合S的距离,Dijkstra是优化未访问的结点Vi 到起始结点s的距离

(2)常用于稠密图

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迎风809

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值