堆優化dijstra(前向星存圖)
堆優化dijstra(前向星存圖)
o(* ̄▽ ̄*)o
上一次學會了spfa安利spfa,激動的不得了,然而
emmmmmm
遇見了這樣的題。洛谷4779最短路標準版!連模板都無法AC使我十分不爽。
所以我決定學習堆優化dijstra。
手寫堆對於我而言是不存在的。所以~STL萬歲
依舊是迪傑斯特拉演算法的思想,尋找當前距離最小的點,然後將它標記為已經確定的點,用它來更新各個沒被確定的點。
emmmm我們選擇優先佇列來確定每一個最小距離的點
普通的優先佇列是大根堆,所以我們選擇用priority_queue<xx,vector<xx>,greater<xx> >q;這樣就變成了小根堆~
為了方便操作,我們用pair來存佇列~(優先佇列會優先比較第一項,不需要過載
pair中的第一項儲存起點到該點的距離,第二項記錄該點是哪一個點。
噹噹噹當看程式碼~~~~~~~!
這個模板的題目就是上邊的洛谷4779
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>//優先佇列在這個庫裡
using namespace std;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;//定義一個小根堆(優先佇列
int n,m,num,s;
int he[100010],d[100010],inq[100010];
//d陣列表示點i和起點之間的距離,inq記錄點i是否已確定,he是前向星存邊~
void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
x=f*x;
}//快讀(有的時候可以神奇的卡入一些神奇的TLE嘿嘿嘿
struct node
{
int nxt;
int to;
int dis;
}edg[200020];//前向星!
void add(int a,int b,int c)
{
edg[++num].to=b;
edg[num].dis=c;
edg[num].nxt=he[a];
he[a]=num;
}//存邊!
void dst(int s)
{
memset(d,0x3f3f3f3f,sizeof(d));//初始化
memset(inq,0,sizeof(inq));
q.push(make_pair(0,s));//起點入隊(堆)了
d[s]=0;//自己到自己,距離0
while(!q.empty())//隊(堆)不是空的,此時距離起點最小的 點在隊首(堆頂)
{
int x=q.top().second;//x:找到了!就是這個點!
q.pop();//出隊(堆),去履行更新其他點的光榮義務
if(inq[x])continue;//如果這是一個已經確定過的點 ,拜拜
inq[x]=1;
int t=he[x];
while(t)//遍歷一遍這個點連向的點,更新最短路
{
if(d[edg[t].to]>d[x]+edg[t].dis&&!inq[edg[t].to])
{
d[edg[t].to]=d[x]+edg[t].dis;
q.push(make_pair(d[edg[t].to],edg[t].to));//被更新了,進去
}
t=edg[t].nxt;
}
}
}//嗷~
int main()
{
int xx,yy,ww;
read(n);read(m);read(s);
for(int i=1;i<=m;i++)
{
read(xx);read(yy);read(ww);
add(xx,yy,ww);//有向圖
}
dst(s);
for(int i=1;i<=n;i++)
cout<<d[i]<<" ";
}