1. 程式人生 > >堆優化dijstra(前向星存圖)

堆優化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]<<" ";
}