Prim算法——最小生成树

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Prim算法——最小生成树相关的知识,希望对你有一定的参考价值。

#include <bits/stdc++.h>
using namespace std;

const int maxn=100000+15;
const int maxm=100000+15;
struct Edge
{
    int x,y,z,next;
    Edge(int x=0,int y=0,int z=0,int next=0):x(x),y(y),z(z),next(next) {}
}edge[maxm*2];
const bool operator < (const Edge &a,const Edge &b)
{
    return a.z>b.z;
 } 
int n,m;
int sumedge,head[maxn];
int ins(int x,int y,int z)
{
    edge[++sumedge]=Edge(x,y,z,head[x]);
    return head[x]=sumedge;
}
priority_queue <Edge> que;
int ans;
bool boo[maxn];
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        ins(x,y,z);
        ins(y,x,z);
    }
    memset(boo,false,sizeof(boo));
    boo[1]=true;
    for (int u=head[1];u;u=edge[u].next) 
      que.push(edge[u]);
    for (int i=1;i<n;i++)    //总共有n-1条边 
    {
        Edge temp;
        temp=que.top();
        for (;boo[temp.y];que.pop(),temp=que.top());
        que.pop();
        ans+=temp.z;
        boo[temp.y]=true;
        for (int u=head[temp.y];u;u=edge[u].next)
         if (!boo[edge[u].y]) que.push(edge[u]);
    }
    printf("%d\n",ans);
    return 0;
 } 

 

′我们可以对该算法里面的各个步骤分别考虑:
′初始化:V’={x},E’={},x是随便一个节点;
′这一步只需要随便选取一个点即可;
′重复下列操作,直到V’=V:
′在E集合当中选择最小的边<u,v>使得u∈V’但是v?V’;
′V’加入节点v,E’加入<u,v>;
 
′对于上面的第二步,实际上我们只需要对于每一个点维护一个V’集合中的点到达该点的最短距离。
′然后每次扫描一遍数组找到我们所需要的v加入V’;
′复杂度为O(N^2+M).
 
′对于上面的第二步操作,我们实际上可以通过堆(优先队列)维护一个满足u∈V’但是v?V’的边集,那么我们就能迅速取出满足要求的边;
′然后当改变了V’的时候,我们就可以根据新加入的节点v对原有的堆进行删除和插入操作。
′需要注意的是,当我们用优先队列实现的时候,我们需要将删除操作延迟。
′复杂度为O((N+M)logN).

以上是关于Prim算法——最小生成树的主要内容,如果未能解决你的问题,请参考以下文章

最小生成树算法:Kruskal算法 Prim算法

HDU1102 最小生成树prim算法

急!数据结构最小生成树prim算法C语言实现

急!数据结构最小生成树prim算法C语言实现

图解:如何实现最小生成树(Prim算法与Kruskal算法)

最小生成树-Prim算法详解(含全部代码)