dijkstra最短路算法

原理

  1. 一开始整张图没有边, 只有一个起点, 设它的距离向量为1.
  2. 更新与起点有连边的点的距离向量.
  3. 取目前距离向量最小的点, 更新与它相连的点的距离向量.
    (可以证明这个距离相连最小的点其距离一定是起点与它的最短距离, 因为若不是最短距离, 则一定会由其它的点更新而来, 而没有距离更小的点).
  4. 更新多次能得到最终所有点的最短距离.

实现

使用堆优化寻找最短距离的点的过程.
注意细节问题, 如果一个点已经被执行过[3]步骤, 那么再对它执行一次[3]步骤就毫无意义了, 所以要记录一下每个点是否被更新过.
这个问题我是在多次超时模板题之后看讨论区发现的.

虽然说是用堆优化, 实际上还是用优先队列priority_queue多一些.另外, pb_ds里面的优先队列好像还要慢一些.

Code

#include <time.h>
#include <queue>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
const int N = 100005;
const int inf = 0x3f3f3f3f;
const int Inf = 0x7fffffff;
using namespace std;

const int MAXIN = 1 << 22;
char IN[MAXIN], *SS = IN, *TT = IN;
#define gc() (SS == TT && (TT = (SS = IN) + fread(IN, 1, MAXIN, stdin), SS == TT) ? EOF : *SS++)

inline int read() {
    int now = 0; register char c = gc();
    for (; !isdigit(c); c = gc());
    for (; isdigit(c); now = now * 10 + c - '0', c = gc());
    return now;
}

struct Edge {
    int v, c; Edge* nxt;
    Edge() {}
    Edge(int _, int __, Edge* ___) : v(_), c(__), nxt(___) {}
} *head[N], pool[400005];

struct Pair{
    int dis, id;
    Pair(int _, int __) : dis(_), id(__) {}
    bool operator < (const Pair& o) const {
        return dis > o.dis;
    }
};
static int cnt = 0;
#define new_Edge(u, v, c) (pool[cnt] = Edge(u, v, c), &pool[cnt++])
#define AddEdge(u, v, c) head[u] = new_Edge(v, c, head[u])

int dis[N], vis[N];

void dijkstra(int s) {
    priority_queue<Pair> que;
    que.push(Pair(0, s));
    memset(dis, 0x3f, sizeof dis);
    dis[s] = false;
    while (not que.empty()) {
        int u = que.top().id; que.pop(); 
        if (vis[u]) continue; vis[u] = true;
        for (auto edge = head[u]; edge; edge = edge->nxt) {
            int v = edge->v;
            if (dis[v] > dis[u] + edge->c) {
                dis[v] = dis[u] + edge->c;
                que.push(Pair(dis[v], v));
            }
        }
    }
}

int main() {
    int n = read(), m = read(), s = read();
    for (int i = 0; i < m; i += 1) {
        int u, v, c;
        u = read(), v = read(), c = read();
        AddEdge(u, v, c);
    }
    dijkstra(s); 
    for (int i = 1; i <= n; i += 1)
        printf("%d ", dis[i] == inf ? Inf : dis[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/qdscwyy/p/9857337.html