最小生成樹----prim演算法的堆優化
阿新 • • 發佈:2019-02-10
用鄰接表+優先佇列可以實現對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;
}