最短経路上の各辺を1本ずつ除いたとき、それぞれの s-t 最短経路長を求めます。 以下では $n$ を頂点数、$m$ を辺数とします。
依存関係
umilib/header.hppumilib/graph/graph.hppumilib/graph/shortest_path_tree.hpp
使い方
#include "umilib/graph/replacement_path.hpp"
戻り値はどちらのアルゴリズムも同じ形式です。
ans[e.id]— 辺eが最短経路上にあるとき: その辺を除いた s-t 最短経路長(存在しない場合はINF)ans[e.id]— 辺eが最短経路上にないとき: 元の最短経路長dist(s, t)
malick_mittal_gupta
vector<T> replacement_path::malick_mittal_gupta(graph<T>& G, int s, int t)
無向グラフの辺置換路を求めます。 内部で Dijkstra を2回(始点 $s$ からと終点 $t$ から)実行し、最短経路木上でのラベリングとスイープによって各辺の置換路を $O((n+m)\log n)$ で求めます。
制約
Gは無向グラフ- 辺重みは非負
計算量
- $O((n + m) \log n)$
roditty_zwick
vector<T> replacement_path::roditty_zwick(graph<T>& G, int s, int t)
辺重みを無視した有向グラフ(非重み付きグラフ)の辺置換路を求めます。 $\sqrt{n}$ 間隔のシードを用いた多始点 BFS で短い迂回路を検出し、非経路頂点のランダムサンプリングで長い迂回路を検出します。 確率的アルゴリズムであり、高確率で正しい答えを返します。
制約
Gは有向グラフ- 辺重みは無視される(各辺のホップ数 = 1)
計算量
- $O(m \sqrt{n} \log n)$ 期待
使用例
#include "umilib/graph/replacement_path.hpp"
int main(){
// Malick-Mittal-Gupta(無向グラフ)
graph<long long> G(5);
G.add_edge(0, 1, 2);
G.add_edge(1, 2, 3);
G.add_edge(2, 3, 1);
G.add_edge(3, 4, 4);
G.add_edge(0, 3, 10);
auto ans = replacement_path::malick_mittal_gupta(G, 0, 4);
// ans[e.id]: 最短経路上の各辺を除いたときの 0-4 最短路長
for(int i = 0; i < G.edge_size(); i++){
auto e = G.get_edge(i);
cout << e.from << "->" << e.to << ": " << ans[i] << "\n";
}
// Roditty-Zwick(有向グラフ、非重み付き)
graph<int> H(4, true);
H.add_edge(0, 1);
H.add_edge(1, 2);
H.add_edge(2, 3);
H.add_edge(0, 2);
auto ans2 = replacement_path::roditty_zwick(H, 0, 3);
for(int i = 0; i < H.edge_size(); i++){
auto e = H.get_edge(i);
cout << e.from << "->" << e.to << ": " << ans2[i] << "\n";
}
}