Johnson algorithm perfection source shortest study notes

Johnson algorithm perfection source shortest study notes

Johnson and Floyd as possible to find a non-negative FIG ring between any two points on a shortest path algorithm. The algorithm proposed by Donald B. Johnson in 1977.

Algorithm Overview

Any two shortest path algorithm can be used to solve Floyd, time complexity \ (O (n-^. 3) \) ;

When no negative weights of the edges may run \ (n-\) times the Dijkstra, the time complexity \ (O (nm \ n-log_2) \) , in a sparse graph would be more excellent;

Johnson algorithm so through a number of methods have a negative view of the edge of the right also applies to the second approach.

detailed steps

First of all points is queued, with relaxation SPFA, marked on top of each point \ (h_u \) ;

Then set the right edge \ (W '(U, V) = W (U, V) + h_u - h_v \) ;

Running \ (n-\) times Dijkstra, this time on the new shortest path between two points in FIG \ (dis' (u, v ) \) and the shortest on the original \ (dis (u, v) \) satisfies \ ( DIS (U, V) = DIS '(U, V) - (h_u - h_v) \) .

Time complexity \ (O (nm \ n-log_2) \) .

Correctness proof

Proof will be divided into two parts:

  1. \(dis(u,v) = dis'(u,v) - (h_u - h_v)\)
  2. No negative side right on the new map.

\((1)\)

Set \ (p_1, \ p_k) path is between \ (P_1, P_2, P_3 \ DOTS, P_ K {-}. 1, P_K \) .

则有:
\[ \sum_{i = 1}^{k - 1} w'(p_i, p_{i + 1}) = \sum_{i = 1} ^ {k - 1} w(p_i, p_{i + 1}) + h_{p_i} - h_{p_{i + 1}} = h_{p_1} - h_{p_k} + \sum_{i = 1}^{k - 1} w(p_i, p_{i + 1}) \]

\((2)\)

\ (h_u \) a top mark is spfa slack off, the triangle inequality is satisfied:

For an edge \ ((U, V) \) , there must be \ (h_u + W (U, V) \ GEQ h_v \) , namely: \ (W (U, V) + h_u - h_v \ GEQ 0 \) .

\(Source\)

Is not necessarily right, no examples, nor filmed

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
int in() {
    int x = 0; char c = getchar(); bool f = 0;
    while (c < '0' || c > '9')
        f |= c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 1e3 + 5, mod = 998244353;

inline void add(int _, int __) {
    _ += __;
    if (_ >= mod)
        _ -= mod;
    if (_ < 0)
        _ += mod;
}

struct edge {
    int next, to, w;
} e[N << 1];
int ecnt = 1, head[N];
int n, m;
int h[N], dis[N][N];

inline void jb(const int u, const int v, const int w) {
    e[++ecnt] = (edge){head[u], v, w}, head[u] = ecnt;
}

void spfa() {
    static int vis[N];
    std::queue<int> q;
    for (int i = 1; i <= n; ++i)
        q.push(i), h[i] = 0, vis[i] = 1;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int i = head[u]; i; i = e[i].next) {
            int v = e[i].to;
            if (h[v] > h[u] + e[i].w) {
                h[v] = h[u] + e[i].w;
                if (!vis[v])
                    q.push(v), vis[v] = 1;
            }
        }
    }
}

void dijkstra(const int s, int *d) {
    static int vis[N];
    memset(vis, 0, sizeof(vis));
    std::priority_queue<std::pair<int, int> > q;
    memset(d, -1, sizeof(int) * (n + 1)); 
    q.push(std::make_pair(0, s));
    while (!q.empty()) {
        int u = q.top().second;
        q.pop();
        if (vis[u])
            continue;
        vis[u] = 1;
        for (int i = head[u]; i; i = e[i].next) {
            int v = e[i].to;
            if (d[v] > d[u] + e[i].w + h[u] - h[v]) {
                d[v] = d[u] + e[i].w + h[u] - h[v];
                q.push(std::make_pair(d[v], v));
            }
        }
    }
    for (int i = 0; i <= n; ++i)
        d[i] -= h[s] - h[i];
}

int main() {
    //freopen("in", "r", stdin);
    n = in(), m = in();
    while (m--) {
        int x = in(), y = in(), z = in();
        jb(x, y, z);
    }
    spfa();
    for (int i = 1; i <= n; ++i)
        dijkstra(i, dis[i]);
    int res = 0;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            add(res, dis[i][j]);
    printf("%d\n", res);
    return 0;
}

Guess you like

Origin www.cnblogs.com/15owzLy1-yiylcy/p/11787586.html
Recommended