Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
グラフアルゴリズムその2 単一始点最短路問題 2018-01-30 宮川 拓
Slide 2
Slide 2 text
参考 『アルゴリズムイントロダクション』, 第3版, 24章「単一始点最短路問題」 2/42
Slide 3
Slide 3 text
def 最短路問題 グラフの頂点間をつなぐ最短の道と、その 重みを求める 3/42
Slide 4
Slide 4 text
最短路問題の分類 単一始点最短路問題: 始点sから各頂点への最短路を求める 単一目的地最短路問題: 各頂点から目的地tへの最短路を求める 本質的には単一始点最短路問題と同じ 単一点対最短路問題: ある頂点対(u, v)間の最短路を求める uを始点とする単一始点最短路問題の部分問題 全点対最短路問題: すべての頂点対(u, v)間の最短路を求める 4/42
Slide 5
Slide 5 text
最短路問題の分類 重み付きグラフ 重みなしグラフ → 幅優先探索で解ける 5/42
Slide 6
Slide 6 text
最短路問題の分類 負の重みを持つ辺が含まれない場合 負の重みを持つ辺が含まれる場合 負の重みを持つ閉路がある場合、最短路 が定義できない頂点対が出現する t v s u -5 -3 2 4 (u, t, v)より(u, t, v, s, t, v), (u, t, v, s, t, v, s, t, v),,, の方が短い 6/42
Slide 7
Slide 7 text
取り上げるアルゴリズム Bellman-Fordアルゴリズム 負の重みを持つ辺が扱える 負閉路が検出できる 遅い Dijkstraのアルゴリズム 負の重みを持つ辺が扱えない 速い 7/42
Slide 8
Slide 8 text
Bellman-Fordアルゴリズム 8/42
Slide 9
Slide 9 text
データ構造 頂点 = { Pred: (暫定)最短路で1つ手前の頂点 Dist: (暫定)最短路で始点からの距離 } // 探索が終わった時点で、暫定でなくなる 辺 = { From: 矢羽側の頂点 To: 矢尻側の頂点 Weight: 辺重み } 9/42
Slide 10
Slide 10 text
Bellman-Fordアルゴリズム 始点のDistを0に、始点以外のDistを∞に設定 loop (頂点の数 - 1) 回: // ← なんで? for すべての辺(From To Weight): D = From.Dist + Weight if D が To.Distよりも短ければ: Toを更新: .Pred=From .Dist=D endif endfor endloop この時点でFrom.Dist+Weight < To.Dist となる辺があれば、グラフは負閉路を含んでいる 10/42
Slide 11
Slide 11 text
例題 c d e b a S 1 2 1 4 6 1 2 3 11/42
Slide 12
Slide 12 text
探索開始 ∞ ∞ ∞ ∞ ∞ 0 1 2 1 4 6 1 2 3 12/42
Slide 13
Slide 13 text
ループ1: d→a ∞ ∞ ∞ ∞ ∞ 0 1 2 1 4 6 1 2 3 変更なし ※From側のDistが∞だから 13/42
Slide 14
Slide 14 text
ループ1: c→b ∞ ∞ ∞ ∞ ∞ 0 1 2 1 4 6 1 2 3 変更なし 14/42
Slide 15
Slide 15 text
ループ1: c→d ∞ ∞ ∞ ∞ ∞ 0 1 2 1 4 6 1 2 3 変更なし 15/42
Slide 16
Slide 16 text
ループ1: b→d ∞ ∞ ∞ ∞ ∞ 0 1 2 1 4 6 1 2 3 変更なし 16/42
Slide 17
Slide 17 text
ループ1: a→c ∞ ∞ ∞ ∞ ∞ 0 1 2 1 4 6 1 2 3 変更なし 17/42
Slide 18
Slide 18 text
ループ1: S→a ∞ ∞ ∞ ∞ 1 0 1 2 1 4 6 1 2 3 変更: ∞→1 18/42
Slide 19
Slide 19 text
ループ1: S→b ∞ ∞ ∞ 1 1 0 1 2 1 4 6 1 2 3 変更: ∞→1 19/42
Slide 20
Slide 20 text
ループ1: S→c 6 ∞ ∞ 1 1 0 1 2 1 4 6 1 2 3 変更: ∞→6 20/42
Slide 21
Slide 21 text
ループ2: d→a 6 ∞ ∞ 1 1 0 1 2 1 4 6 1 2 3 変更なし 21/42
Slide 22
Slide 22 text
ループ2: c→b 6 ∞ ∞ 1 1 0 1 2 1 4 6 1 2 3 変更なし 22/42
Slide 23
Slide 23 text
ループ2: c→d 6 7 ∞ 1 1 0 1 2 1 4 6 1 2 3 変更: ∞→7 23/42
Slide 24
Slide 24 text
ループ2: b→d 6 5 ∞ 1 1 0 1 2 1 4 6 1 2 3 変更: 7→5 24/42
Slide 25
Slide 25 text
ループ2: a→c 3 5 ∞ 1 1 0 1 2 1 4 6 1 2 3 変更: 6→3 25/42
Slide 26
Slide 26 text
ループ2: S→a 3 5 ∞ 1 1 0 1 2 1 4 6 1 2 3 変更なし 26/42
Slide 27
Slide 27 text
ループ2: S→b 3 5 ∞ 1 1 0 1 2 1 4 6 1 2 3 変更なし 27/42
Slide 28
Slide 28 text
ループ2: S→c 3 5 ∞ 1 1 0 1 2 1 4 6 1 2 3 変更なし 28/42
Slide 29
Slide 29 text
ループ5終了時点 3 4 ∞ 1 1 0 1 2 1 4 6 1 2 3 観察: 各頂点に、0/1個のpredが設定されている 最短路の部分経路もまた最短路である 29/42
Slide 30
Slide 30 text
Bellman-Fordアルゴリズム 始点のDistを0に、始点以外のDistを∞に設定 loop (頂点の数 - 1) 回: // ← なんで? for すべての辺(From To Weight): D = From.Dist + Weight if D が To.Distよりも短ければ: Toを更新: .Pred=From .Dist=D endif endfor endloop この時点でFrom.Dist+Weight < To.Dist となる辺があれば、グラフは負閉路を含んでいる 30/42
Slide 31
Slide 31 text
繰り返し回数の直感的理解 頂点の数だけが与えられている場合、 最短路の辺の数は高々(頂点数-1) 例: 6頂点(S, a, b, c, d, e)→5辺 (頂点数-1)回だけ繰り返せば、すべての 最短路のすべての辺がたどられるはず 31/42
Slide 32
Slide 32 text
Bellman-Fordアルゴリズム 始点のDistを0に、始点以外のDistを∞に設定 loop (頂点の数 - 1) 回: for すべての辺(From To Weight): D = From.Dist + Weight if D が To.Distよりも短ければ: Toを更新: .Pred=From .Dist=D endif endfor endloop この時点でFrom.Dist+Weight < To.Dist となる辺があれば、グラフは負閉路を含んでいる 計算量: O(頂点数*辺数) 32/42
Slide 33
Slide 33 text
Dijkstraのアルゴリズム 33/42
Slide 34
Slide 34 text
データ構造 頂点 = { Pred: (暫定)最短路で1つ手前の頂点 Dist: (暫定)最短路で始点からの距離 Neibors: (矢印の先の頂点, 重み)の集合 } 頂点の優先度付きキュー = { extractMin(): 距離が最も小さい頂点を抜き出す decreaseKey(V, Dist): 頂点Vの距離を更新する } // 距離を優先度とする 34/42
Slide 35
Slide 35 text
Dijkstraのアルゴリズム 始点のDistを0に、始点以外のDistを∞に設定 Q = すべての頂点を含む優先度付きキュー while Qが空でない間: Min = Q.extractMin() for すべてのMin.neibors → (V, Weight) : D = Min.dist + Weight if DがV.distよりも短ければ: Vを更新: .Pred=Min .Dist=D Q.decreaseKey(V, D) endif endfor endwhile 35/42
Slide 36
Slide 36 text
直感的な理解 最短路と距離が確定した頂点の集合S 最短路と距離が未確定の頂点の集合Q Sの 中 の 頂 点 は 最短路が確定している 最短路は Sに含まれる 頂点だけで構成される 36/42
Slide 37
Slide 37 text
直感的な理解 最短路と距離が確定した頂点の集合S 最短路と距離が未確定の頂点の集合Q Qの 中 の 頂 点 は 最短路が未確定 Sの中の頂点から来る 道があれば、 そのいずれかが 暫定最短路として 設定されている 37/42
Slide 38
Slide 38 text
直感的な理解 最短路と距離が確定した頂点の集合S 最短路と距離が未確定の頂点の集合Q Min Qか ら 、 暫定距離が最も短い 頂点Minを選ぶ 38/42
Slide 39
Slide 39 text
直感的な理解 最短路と距離が確定した頂点の集合S 最短路と距離が未確定の頂点の集合Q Min Minの最短路は 確定できる! Qの 中 の 他 の 頂 点 を たどる道が 最短路であることは ないから ※ 負辺はない前提 39/42
Slide 40
Slide 40 text
直感的な理解 最短路と距離が確定した頂点の集合S 最短路と距離が未確定の頂点の集合Q Min MinからQへの 暫定最短路があれば 更新する 40/42
Slide 41
Slide 41 text
Dijkstraのアルゴリズムの計算量 始点のDistを0に、始点以外のDistを∞に設定 Q = すべての頂点を含む優先度付きキュー while Qが空でない間: Min = Q.extractMin() for すべてのMin.neibors → (V, Weight) : D = Min.dist + Weight if DがV.distよりも短ければ: Vを更新: .Pred=Min .Dist=D Q.decreaseKey(V, D) endif endfor endwhile 頂 点 数 回 実 行 さ れ る だ い た い 辺 数 回 実 行 さ れ る 41/42
Slide 42
Slide 42 text
Dijkstraのアルゴリズムの計算量 優先度付きキューの操作の計算量に依存 優先度付き キューの実装 extractMin decrease Key Dijkstraの計算量 2 分ヒープ Θ(log N) Θ(log N ) Θ(辺数* log頂点数 +頂点数* log頂 点 数) フィボナッチ ヒープ Θ(log N) Θ(1) ※ならし Θ(辺数 +頂点数* log頂 点 数) ※ならし 計算量は漸近的にフィボナッチヒープが有利 フィボナッチヒープの実装は複雑、 2分ヒープは単純なので、 グラフが小さい場合は 2分ヒープを使う方が有利 42/42 ※N = 優先度付きキューの要素数