1. 程式人生 > >最小生成樹prim演算法(模板)

最小生成樹prim演算法(模板)

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; }