最小生成树prim算法(模板)

我是研究僧i 提交于 2020-03-14 03:48:52

prim算法适合稠密图,即边数较多而点较少的情况,时间复杂度为O(n2),堆优化的情况下,如果点数为m,边数为n,可以达到O(nlogm).思想很简单,就是每次寻找一条由已加入集合的点和与它们相邻的没加入集合的点的权值最小边,进行n-1次就找出来了,也是贪心的思想,实现就是随便找一个初始节点,然后建一个最小堆(边小的先pop出来),把该节点的vis值置为1,遍历该节点相邻的节点,如果没有被vis标记过,就加入边到堆中,扫完了以后处理堆中数据,如果弹出的边被标记过就pop,没有就取出来,把边通往的节点置为key,下次就加入key节点有关没有标记过的边。循环n-1次,把每一次堆弹出边的值累加起来就是最小生成树的值了

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

const int maxn=1005;

struct Edge{
    int to,dist;
    Edge(int t,int d):to(t),dist(d){}
    bool operator<(const Edge& e)const{
        return dist>e.dist;
    }
};

int n,m;
bool vis[maxn];
vector<Edge> g[maxn];
priority_queue<Edge> que;

void prim(){
    memset(vis,0,sizeof(vis));
    while(que.size()) que.pop();

    for(int i=0;i<g[0].size();++i) que.push(g[0][i]);
    vis[0]=true;

    int ans=0;
    for(int cnt=1;cnt<n;++cnt){
        while(que.size() && vis[que.top().to]) que.pop();
        Edge e=que.top();
        ans+=e.dist;
        int v=e.to;
        vis[v]=true;
        for(int i=0;i<g[v].size();++i){
            if(!vis[g[v][i].to]) que.push(g[v][i]);
        }
    }
    printf("%d\n",ans);
}

int main(){
    while(scanf("%d%d",&n,&m)==2){
        for(int i=0;i<n;++i) g[i].clear();
        for(int i=0;i<m;++i){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            g[u-1].push_back(Edge(v-1,w));
            g[v-1].push_back(Edge(u-1,w));
        }
        prim();
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;

const int maxn=1005;

struct Edge{
    int from,to,dist;
    Edge(int f,int t,int d):from(f),to(t),dist(d){}
};

struct HeapNode{
    int d,u;
    HeapNode(int dd=0,int uu=0):d(dd),u(uu){}
    bool operator<(const HeapNode& rhs)const{
        return d>rhs.d;
    }
};

int n,m;
bool done[maxn];
vector<Edge> edges;
vector<int> g[maxn];

void init(){
    for(int i=0;i<n;++i) g[i].clear();
    edges.clear();
}

void add(int from,int to,int dist){
    int num;
    edges.push_back(Edge(from,to,dist));
    num=edges.size()-1;
    g[from].push_back(num);
}

int prim(int s){
    priority_queue<HeapNode> que;
    while(que.size()) que.pop();
    memset(done,0,sizeof(done));

    done[s]=true;
    for(int i=0;i<g[s].size();++i){
        Edge& e=edges[g[s][i]];
        que.push(HeapNode(e.dist,e.to));
    }
    int ans=0;
    for(int cnt=1;cnt<n;++cnt){
        HeapNode x;
        while(que.size()){
            x=que.top();
            if(!done[x.u]) break;
            que.pop();
        }
        ans+=x.d;
        done[x.u]=true;
        for(int i=0;i<g[x.u].size();++i){
            Edge& e=edges[g[x.u][i]];
            if(!done[e.to]) que.push(HeapNode(e.dist,e.to));
        }
    }
    return ans;
}

int main(){
    while(scanf("%d%d",&n,&m)==2){
        init();
        for(int i=0;i<m;++i){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u-1,v-1,w);
            add(v-1,u-1,w);
        }
        printf("%d\n",prim(0));
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;

const int maxn=1005;

struct HeapNode{
    int d,u;
    HeapNode(int dd=0,int uu=0):d(dd),u(uu){}
    bool operator<(const HeapNode& e)const{
        return d>e.d;
    }
};

int n,m;
int g[maxn][maxn];
bool done[maxn];

int prim(int s){
    priority_queue<HeapNode> que;
    while(que.size()) que.pop();
    memset(done,0,sizeof(done));

    done[s]=true;
    for(int i=0;i<n;++i){
        if(g[s][i]!=-1) que.push(HeapNode(g[s][i],i));
    }
    int ans=0;
    for(int cnt=1;cnt<n;++cnt){
        HeapNode x;
        while(que.size()){
            x=que.top();
            if(!done[x.u]) break;
            que.pop();
        }
        ans+=x.d;
        done[x.u]=true;
        for(int i=0;i<n;++i){
            if(g[x.u][i]!=-1 && !done[i]) que.push(HeapNode(g[x.u][i],i));
        }
    }
    return ans;
}

int main(){
    while(scanf("%d%d",&n,&m)==2){
        memset(g,-1,sizeof(g));
        for(int i=0;i<m;++i){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            g[u-1][v-1]=g[v-1][u-1]=w;
        }
        printf("%d\n",prim(0));
    }
    return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!