ダイクストラ法とその制約

ダイクストラ法はグラフ理論における辺の重みが非負数の場合の単一始点最短経路問題を解くための最良優先探索によるアルゴリズムです。1959年エドガー・ダイクストラによって考案されたアルゴリズムでOSPFなどのインターネットルーティングプロトコルや、カーナビの経路探索や鉄道の経路案内においても利用されています。

時間計算量は頂点数を V、辺の数を E としたとき、O((V + E) × log(V)) です。log(V)がつくのは実装に優先度つきキューを用いるからです。

注意しなければならないのは、負の重みをもつ辺があるグラフでは使えないという制約があることです。では負の重みをもつ辺があるグラフで最短経路問題を解くときはどうすればよいのでしょうか?

ベルマンフォード法はひとつの選択です。ベルマンフォード法の時間計算量は O(V × E) です。ダイクストラ法と比べると計算量が増えてしまいますが、こちらは負の重みをもつ辺があっても使えます。

とはいえ、同じグラフで何度も最短経路問題を解かなければならない場合は計算量が少ないダイクストラ法を使いたいものです。うまくグラフを負辺を持たないグラフに変換する方法はないものでしょうか?

これに回答を与えるのがポテンシャルです。

ポテンシャルとは?

頂点 u から頂点 v への有向辺が張られていてその重みを w(u, v) で表すことにします。このとき、頂点 i に重み p(i) をもたせることで w(u, v) ≧ p(v) – p(u) が常に成立する場合、実行可能ポテンシャルが存在すると定義します。

w(u, v) + p(u) – p(v) を被約コスト c(u, v) と定義します。また被約コストによって重み付けられたグラフを被約グラフと呼ぶことにします。

パス上の辺の重みの総和と被約コストの総和の差は端点のみに依存します。頂点 v1, v2, …, vk を通るパスの辺の被約コストの総和を計算してみると

c(v1, v2) + c(v2, v3) + … + c(v{k- 1}, vk)
= {w(v1, v2) + p(v1) – p(v2)} + {w(v2, v3) + p(v2) – p(v3)} + … + {w(v{k – 1}, vk) + p(v{k – 1}) – p(vk)}
= w(v1, v2) + w(v2, v3) + … + w(v{k – 1}, vk) + p(v1) – p(vk)

となり、移項すると

(v1, v2) + w(v2, v3) + … + w(v{k – 1}, vk) = c(v1, v2) + c(v2, v3) + … + c(v{k- 1}, vk) + p(vk) – p(v1)

となります。この式が意味するものは s から t までの最短経路長は 被約グラフの s から t までの最短経路長に t のポテンシャルを加え s のポテンシャルを引いたものであるということです。

また負閉路を持たないことと、実行可能ポテンシャルが存在することは同値です。

E – Skiing

E – Skiing

問題の概要

スキー場には N 個の広場があり、広場 i の標高は H[i] である。
2 つの広場を双方向に結ぶ M 本の坂があり、i 本目の坂は広場 U[i] と広場 V[i] を双方向に結んでいる。

「楽しさ」を以下のように定義する。

広場 X が広場 Y より標高が真に高い場合、その標高差、すなわち H[X] – H[Y] だけ楽しさが増加する。
広場 X が広場 Y より標高が真に低い場合、その標高差の 2 倍、すなわち 2(H[Y] – H[X]) だけ楽しさが減少する。
広場 X と広場 Y の標高が等しい場合、楽しさは変化しない。
楽しさは負の値になることもある。

最初、広場 1 におり、楽しさは 0 である。0 本以上のいくつかの坂を移動した後に好きな広場で行動を終えることができるとしたとき、楽しさとしてありうる最大の値を求めよ。

楽しさの -1 倍をコストとみなすことで、問題文は「頂点 1 からの最小移動コストが最小となる頂点の移動コストを求めよ」という最短経路の問題に言い換えることができます。

この問題を直接ダイクストラ法で解くことはできません。このグラフには負のコストをもつ辺が含まれているからです。一方で、ベルマンフォード法では計算量が O(NM) となるので間に合いません。そこで、ポテンシャルを用いてこの問題をダイクストラ法が適用できる形にすることを考えます。

実は標高がポテンシャルとして使えます。

頂点 v1, v2 の標高を h1, h2 としたとき、h1 ≧ h2 なら以下のように辺が張られます。

頂点 v1 から 頂点 v2 へ 重み h2 – h1 の辺
頂点 v2 から 頂点 v1 へ 重み (h1 – h2) × 2 の辺

ポテンシャルの定義と比較してみると以下の不等式が成立しています。

頂点 v1 から 頂点 v2: h2 – h1 ≧ h2 – h1
頂点 v2 から 頂点 v1: (h1 – h2) × 2 ≧ h1 – h2

被約コストは以下のようになります。

頂点 v1 から 頂点 v2: h2 – h1 – (h2 – h1) = 0
頂点 v2 から 頂点 v1: (h1 – h2) * 2 – (h1 – h2) = h1 – h2

なので以下のような被約グラフを構築します。

頂点 v1 から 頂点 v2: 重み 0 の辺を張る
頂点 v2 から 頂点 v1: 重み h1 – h2 の辺を張る

被約グラフにおいてダイクストラ法で頂点 0 から各頂点への最短経路長を調べます。各頂点への最短経路長が求まったらそれらに各頂点の標高を加えて頂点 1 の標高を引きます。これが各頂点への最小コストです。このなかから最小値を求めます。この符号を反転させたものが問題の解です。

ポテンシャルを求めて被約グラフを構築するには?

負の重みをもつ辺があるグラフからポテンシャルを求め、被約グラフを構築するにはどうすればよいでしょうか?

ポテンシャルを求めるにはベルマンフォード法をつかいます。

まず超頂点 S を追加し、そこから各頂点へ重み 0 の有向辺を張り、S から各頂点への最短距離を求めます。この最短距離がポテンシャルとなります。なので負の重みをもつ辺が存在しない場合、ポテンシャルは 0 です。

なぜこの方法でポテンシャルを求めることができるのでしょうか?

h は 超頂点 S からの最短距離、w(u, v) は u から v までの距離なので、任意の辺 u → v について h[v] ≦ h[u] + w(u, v) が成立します。これを変形すると、w(u, v) ≧ h[v] – h[u] となります。これはポテンシャルの定義と一致します。

ポテンシャルを求めることができたら被約グラフを構築して最短経路長を求めます。