• Prim算法


    普里姆算法(Prim算法),

    图论中的一种算法,可在加权连通图里搜索最小生成树。

    意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小。

    算法描述

    1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
    2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
    3).重复下列操作,直到Vnew = V:
    a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
    b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
    4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。
     

    图例描述

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll N=5e4+2;
    ll n,m,h[N],tot,cnt;
    struct node{
        ll v,c,ne;
    }e[N*40];
    void add(ll u,ll v,ll c)
    {
        tot++;e[tot]=(node){v,c,h[u]};h[u]=tot;
    }
    struct OK{
        ll i,d;
        friend bool operator <(OK A,OK B)
        {
            return A.d>B.d;
        }
    }ff;
    priority_queue<OK>q;
    ll ans,d[N];//d[i]表示距离已经选的图里的点的最短距离
    bool v[N];
    void Prim()
    {
        for(ll i=1;i<=n;++i) d[i]=1e18;
        d[1]=0;q.push((OK){1,0});
        while(!q.empty())
        {
            ff=q.top();q.pop();
            if(v[ff.i]) continue;
            v[ff.i]=1;ans+=d[ff.i];cnt++;
            for(ll i=h[ff.i];i;i=e[i].ne)
            {
                if(d[e[i].v]>e[i].c)
                {
                    d[e[i].v]=e[i].c;
                    q.push((OK){e[i].v,d[e[i].v]});
                }
            }	
        }
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(ll i=1,x,y,z;i<=m;++i)
        {
        	scanf("%lld%lld%lld",&x,&y,&z);
        	add(x,y,z);add(y,x,z);
        }
        Prim();
        if(cnt==n) cout<<ans;
        else puts("orz");
        return 0;
    }
  • 相关阅读:
    如何给博客园添加背景canvas线条动画背景
    过去-现在-未来
    如何将图片转化为代码图片
    css3炫酷登录页面
    图片跟随鼠标移动特效
    css3实现鼠标移入图片特效
    在线上传图片获取url
    《程序员修炼之道:从小工到专家》读后感01
    动手动脑-随机数和重载
    JAVA学习第三周
  • 原文地址:https://www.cnblogs.com/adelalove/p/8525381.html
Copyright © 2020-2023  润新知