Dijkstra+優先隊列 堆優化


關於堆優化

傳統\(Dijkstra\),在選取中轉站時,是遍歷取當前最小距離節點,但是我們其實可以利用小根堆(STL的priority_queue)優化這個過程,從而大大降低復雜(\(O(V^2+E) -> O((V+E)lgV)\)

另外,需要注意,因為\(Dijkstra\)本質是貪心,每一次選擇中轉站必須保證最優,而負邊權會使當前中轉站不為最優,所以不能處理含有負邊權的圖

代碼

#include <cstdio>
#include <queue>
#include <vector>
#define MAXN 200010
#define INF 0x3fffffff
using namespace std;
struct edge{
    int v,w;
    edge(int v, int w):v(v),w(w){}
};
vector <edge> mp[MAXN];
int dis[MAXN];
bool vis[MAXN];
int n,m,s;
struct node{
    int v,dis;
    node(int v, int dis):v(v),dis(dis){}
    const bool operator < (const node &a) const{
        return a.dis < dis;
    }
};
priority_queue <node> q;

int read(){
    char ch;int s=0;
    ch = getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s;
}

void dj(){
    for(register int i=1;i<=n;i++)
        dis[i]=INF;
    dis[s]=0;
    q.push(node(s, 0));
    while(!q.empty()){
        node cur = q.top();
        q.pop();
        if(vis[cur.v])  continue;
        vis[cur.v] = 1;
        for(register int i=0;i<mp[cur.v].size();i++){
            edge to = mp[cur.v][i];
            if(vis[to.v]) continue;
            if(dis[to.v]>to.w+dis[cur.v]){
                dis[to.v]=to.w+dis[cur.v], q.push(node(to.v, dis[to.v]));
            }
        }
    }
    for(register int i=1;i<=n;i++)
        printf("%d ", dis[i]);
}

int main()
{
    n=read(),m=read(),s=read();
    for(register int i=1;i<=m;i++){
        int u,v,w;
        u=read(),v=read(),w=read();
        mp[u].push_back(edge(v, w));
    }
    dj();
    return 0;
}

參考

水郁 - Dijkstra+heap和SPFA的區別


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM