johnson 和 floyd 一樣,是一種能求出無負環圖上任意兩點間最短路徑的演算法。該演算法在 1977 年由 donald b. johnson 提出。
任意兩點最短路可以用 floyd 演算法解決,時間複雜度 \(o(n ^ 3)\);
在沒有負權邊時,可以跑 \(n\) 次 dijkstra,時間複雜度 \(o(nm \log_2 n)\),在稀疏圖上會比較優秀;
johnson 演算法通過一些方法使有負權邊的圖也適用於第二種做法。
先把所有點加入佇列,用 spfa 進行鬆弛,每個點上的頂標記為 \(h_u\);
再將邊權設為 \(w'(u,v) = w(u,v) + h_u - h_v\);
跑 \(n\) 次 dijkstra,此時新圖上兩點間的最短路 \(dis'(u,v)\) 和原圖上最短路 \(dis(u,v)\) 滿足 \(dis(u,v) = dis'(u,v) - (h_u - h_v)\)。
時間複雜度 \(o(nm \log_2 n)\)。
證明將分為兩部分:
\(dis(u,v) = dis'(u,v) - (h_u - h_v)\);
新圖上沒有負權邊。
\((1)\):
設 \(p_1, p_k\) 間的一條路徑為 \(p_1, p_2 , p_3 \dots , p_, p_k\)。
則有:\[\sum_^ w'(p_i, p_) = \sum_ ^ w(p_i, p_) + h_ - h_} = h_ - h_ + \sum_^ w(p_i, p_)
\]\((2)\):
\(h_u\) 頂標是用 spfa 鬆弛過的,所以滿足三角形不等式:
對於一條邊 \((u,v)\),一定有 \(h_u + w(u,v) \geq h_v\) ,即:\(w(u,v) + h_u - h_v \geq 0\)。
不一定是對的,沒有例題,也沒有拍過
upd:模板 luogup5905;afo,要改的太多,懶得改。
#include #include #include #include int in()
templateinline void chk_min(t &_, t __)
templateinline void chk_max(t &_, t __)
const int n = 1e3 + 5, mod = 998244353;
inline void add(int _, int __)
struct edge 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) , head[u] = ecnt;
}void spfa() }}
}void dijkstra(const int s, int *d) }}
for (int i = 0; i <= n; ++i)
d[i] -= h[s] - h[i];
}int main()
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;
}
Johnson演算法 多源最短路演算法
請不要輕易點選標題 乙個適用於求可含負邊權的稀疏圖的多源最短路演算法 時間複雜度 o n cdot m cdot log m n cdot m 空間複雜度 o n m 該演算法綜合利用了dijkstra演算法和bellman ford演算法 不要慌,雖然有負邊但dijkstra可以跑 在開始講解之前...
Johnson全源最短路
例題 p5905 模板 johnson 全源最短路 首先考慮求全源最短路的幾種方法 好像 只有dijkstra還有希望?但負權邊處理不了真是很棘手啊。一種方法是讓每條邊都加上乙個數 x 使得邊權為正,但考慮下圖 1 到 2 的最短路應為 1 3 4 2 長度為 1 如果我們把每條邊的邊權都加上 5 ...
johnson全源最短路
一下都假設該有向圖 無向圖同理 有n個點,m條邊。談及全源最短路,第乙個想到的是弗洛伊德演算法,簡單有效,因為並非本篇文章重點,所以只是把 放在這裡 int main 唯一要注意的就是必須要列舉轉折點。時間複雜度o n 3 當n很大時不是乙個可以接受的數字。或者跑n遍單元最短路。你可以用spfa跑,...