1. 程式人生 > >最小生成樹----prim演算法的堆優化

最小生成樹----prim演算法的堆優化

用鄰接表+優先佇列可以實現對prim演算法的堆優化

prim的思想還是沒有改變,還是從任意一個點開始選擇,找出這個點連線的所有的邊,然後找出最短的,選中這條邊加入到生成樹中,列舉每一個樹頂點到每一個費數頂點的所有的邊,然後找最短的邊加入到生成樹,一直加邊n-1次,直到所有的頂點都被加入到生成樹中

在實現的時候,我們先選取隨便一個點,然後用一個pair型別儲存當前的點的dis值和當前的點的編號,然後讓dis值比較小的先出隊,然後取隊首,噹噹前點沒有被訪問過時,記錄cnt和sum,然後遍歷這個點連線的所有邊,進行鬆弛操作.

#include <cstdio>
#include <cstring>
#include <cctype> #include <stdlib.h> #include <string> #include <map> #include <iostream> #include <set> #include <stack> #include <cmath> #include <queue> #include <vector> #include <algorithm> using namespace std; #define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll; typedef pair<int,int> pir; const int N=5000+10; const int M=200000+10; int first[N],tot; int vis[N],dis[N],n,m; priority_queue <pir,vector<pir>,greater<pir> >q; struct edge { int v,w,next; } e[M*2]; void add_edge(int u,int v,int w) { e[tot].v=v; e[tot].w=w; e[tot].next=first[u]; first[u]=tot++; } void
init() { mem(first,-1); tot=0; mem(dis,127); } void prim() { int cnt=0,sum=0; dis[1]=0; q.push(make_pair(0,1)); while(!q.empty()&&cnt<n) { int d=q.top().first,u=q.top().second; q.pop(); if(!vis[u]) { cnt++; sum+=d; vis[u]=1; for(int i=first[u]; ~i; i=e[i].next) if(e[i].w<dis[e[i].v]) { dis[e[i].v]=e[i].w; q.push(make_pair(dis[e[i].v],e[i].v)); } } } if(cnt==n) printf("%d\n",sum); else puts("orz"); } int main() { int u,v,w; init(); scanf("%d%d",&n,&m); for(int i=1; i<=m; i++) { scanf("%d%d%d",&u,&v,&w); add_edge(u,v,w); add_edge(v,u,w); } prim(); return 0; }