Dijkstra+优先队列 堆优化

Posted santiego

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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),在选取中转站时,是遍历取当前最小距离节点,但是我们其实可以利用小根堆(STL的priority_queue)优化这个过程,从而大大降低复杂((O(V2+E) -> O((V+E)lgV))

另外,需要注意,因为(Dijkstra)本质是贪心,每一次选择中转站必须保证最优,而负边权会使当前中转站不为最优,所以不能处理含有负边权的图

以上是关于Dijkstra+优先队列 堆优化的主要内容,如果未能解决你的问题,请参考以下文章

优先队列(堆优化)的dijkstra算法

最短路Dijkstra+ 链式前向星+ 堆优化(优先队列)

dijkstra模板(好像是斐波那契额堆优化,但我为什么看起来像优先队列优化,和spfa一样)

最短路径-dijkstra算法

配对堆优化Dijkstra算法小记

优先级队列(小顶堆)的dijkstra算法