最小生成树(二)prim

今天为大家带来最小生成树的第二种实现方式,比起kruskal来说,prim相对要复杂一些,在稠密图的表现中表现较好,最优情况下也是nlogn级别.

描述:

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来描述所得到的最小生成树。---百度百科
 
 

输入:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出:
7
 
 
#include <bits/stdc++.h>
#define N 999999
using namespace std;
int dis[N],cnt=1,m,out,n;
int now=1,totw;
int head[N];
int u,v,w;
struct node
{
    int v;
    int next;
    int w;
} e[N<<1];
int vis[N];
inline void add(int u,int v,int w)
{
    e[cnt].v=v;
    e[cnt].next=head[u];
    e[cnt].w=w;
    head[u]=cnt;
    cnt++;
}
inline int prim()
{
 memset(dis,N,sizeof(dis));
 
    for(int i=head[1]; i; i=e[i].next)
    {
        dis[e[i].v]=min(dis[e[i].v],e[i].w);
    }
    while(out!=n-1)
    {

        int minn=N;
        vis[now]=1;
        for(int i=1; i<=n; i++)
        {
            if(!vis[i]&&minn>dis[i])
            {
                minn=dis[i];
                now=i;
            }
        }
        totw+=minn;
        for(int i=head[now]; i; i=e[i].next)
        {
            int v=e[i].v;
            if(dis[v]>e[i].w&&!vis[v])
            {
                dis[v]=e[i].w;
            }
        }
        out++;
    }
    return totw;
}
int main()
{
    cin>>n>>m;
    for(int i=1; i<=m; i++)
    {
        cin>>u>>v>>w;
        add(u,v,w);
        add(v,u,w);
    }
    cout<<prim();
    return 0;
}

 

posted @ 2020-02-10 17:42  remarkableboy  阅读(174)  评论(0编辑  收藏  举报