1. 程式人生 > >圖論——最小生成樹prim+鄰接表+堆優化

圖論——最小生成樹prim+鄰接表+堆優化

pop turn str 第一個元素 for prior ace 最小生成樹 \n

今天學長對比了最小生成樹最快速的求法不管是稠密圖還是稀疏圖,prim+鄰接表+堆優化都能得到一個很不錯的速度,所以參考學長的代碼打出了下列代碼,make_pair還不是很會,大體理解的意思是可以同時綁定兩種元素(和struct差不多)但加入堆的時候以第一個元素來進行優先隊列,建立的是大根堆由於每次要選出最小的邊所以把邊取反,最小的那個邊加上符號就變成最大的了,大體上就是這樣。prim的思想。

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include
<ctime> #include<cmath> #include<algorithm> #include<iomanip> #include<vector> #include<queue> #include<stack> #include<map> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();} return x*f; } priority_queue<pair<int,int> >q; int nex[200001<<1],ver[200001<<1],e[200001<<1],lin[200001<<1],len=0; void add(int x,int y,int z) { ver[++len]=y; nex[len]=lin[x]; lin[x]=len; e[len]=z; }
int n,m; int vis[5009],d[5009]; int ans=0,cnt=0; void prim() { memset(vis,0,sizeof(vis)); memset(d,10,sizeof(d)); d[1]=0;q.push(make_pair(0,1)); while(q.size()!=0&&cnt<n)//註意這個地方是和,兩個之中有一個不滿足就退出 { int u=q.top().second,dis=-q.top().first;q.pop(); if(vis[u]==1)continue; ans+=dis;vis[u]=1;cnt++; for(int i=lin[u];i;i=nex[i]) { int tn=ver[i]; if(e[i]<d[tn]) { d[tn]=e[i];q.push(make_pair(-d[tn],tn)); } } } } int main() { freopen("1.in","r",stdin); n=read();m=read(); for(int i=1;i<=m;i++) { int x,y,z; x=read();y=read();z=read(); add(x,y,z); add(y,x,z); } prim(); if(cnt==n) printf("%d\n",ans); else printf("orz\n"); return 0; }
View Code

多情自古原多病,清鏡憐清影。

圖論——最小生成樹prim+鄰接表+堆優化