ダイクストラのアルゴリズムが負の重みのエッジに対して機能しないのはなぜですか?


121

単一ソースの最短パスに対するダイクストラのアルゴリズムが、エッジが負でない必要があると仮定する理由を誰かに教えてもらえますか?

私は負のウェイトサイクルではなく、エッジのみについて話しています。


3
良い例で正しい答えは次のようになります。stackoverflow.com/questions/6799172/...
Amitk

回答:


175

ダイクストラのアルゴリズムでは、頂点が「クローズ」としてマークされた(そしてオープンセットから外れた)ことを思い出してください-アルゴリズムはその最短パスを検出し、このノードを再度開発する必要はありません-これまでに作成されたパスを想定しますパスは最短です。

しかし、負の重みでは-それは本当ではないかもしれません。例えば:

       A
      / \
     /   \
    /     \
   5       2
  /         \
  B--(-10)-->C

V={A,B,C} ; E = {(A,C,2), (A,B,5), (B,C,-10)}

Aのダイクストラは最初にCを開発し、後で見つけられない A->B->C


もう少し深い説明を編集してください:

これは重要であることに注意してください。各緩和ステップで、アルゴリズムは「閉じた」ノードへの「コスト」が実際に最小であることを前提としているため、次に選択されるノードも最小です。

アイデアは次のとおりです。頂点に開いた頂点があり、そのコストが最小になる場合- 任意の頂点に任意の正の数を追加することにより-最小性は決して変更されません。
正の数に対する制約なし-上記の仮定は当てはまりません。

「閉じられた」各頂点は最小限に「知っている」ので、「振り返る」ことなく、安全にリラックスステップを実行できます。「振り返る」必要がある場合-Bellman-Fordは、そうすることの再帰的な(DP)ソリューションを提供します。


5
申し訳ありませんが、エラーは発生していません。最初A->Bに5とA->C2になります。次ににB->Cなり-5ます。したがって、の値はベルマンフォードC-5同じになります。これが正しい答えを与えていないのはなぜですか?
Anirban Nag 'tintinmj' 2014年

5
@tintinmjが最初に、DijkstraはA値0のノードを「閉じます」。次に、最小値のノードでBある5とC2 を探します。最小値はCなのでC、値2で閉じ、決して後戻りしません。後でB閉じられると、Cはすでに「閉じられている」ため、の値を変更できません。
2014年

4
@amitダイクストラのアルゴリズムはどのようにパスを見つけられないのA -> B -> Cですか?最初にCの距離を2に更新し、次にBの距離を5に更新します。グラフにからの発信エッジがないと仮定すると、C訪問時に何もしませんC(その距離は2のままです)。次にD、の隣接ノードにアクセスします。隣接ノードはのみCで、新しい距離は-5です。ダイクストラ法では、我々はまた、我々が到達する親のトラック(および更新)ノード、およびからそれをやっておくことを注意C、あなたが親を取得しますB、その後、A正しい結果が得られ、。何が欠けていますか?
nbro 2015

12
@amitあなたの推論の問題(私は思う)、そして私が他の人がそれをしているのを見た(奇妙なことに)、あなたはアルゴリズムがすでに最短距離が決定されている(そして私たちが終わった)ノードを再検討しないと思うということです、しかし、これは正しくありません。そのため、「緩和」ステップがあります。グラフのすべてのノードを反復処理し、隣接ノードのいずれかが隣接ノードであっても、それぞれのノードについて、隣接ノードを反復処理します。たとえば、min-priorityキューからすでに削除されています。
nbro 2015

10
@amitこの例が実際に理にかなっている同様の質問に対するこの回答を確認してください:stackoverflow.com/a/6799344/3924118
nbro

37

ソースをVertex Aとして以下のグラフを検討してください。まず、ダイクストラのアルゴリズムを自分で実行してみてください。

ここに画像の説明を入力してください

私の説明でダイクストラのアルゴリズムを参照するときは、以下に実装されているダイクストラのアルゴリズムについて話します。

ダイクストラのアルゴリズム

したがって、最初に各頂点に割り当てられたソースから頂点までの距離)を開始すると、

初期化

最初にQ = [A、B、C]の頂点を抽出しますこれは最小値、つまりAを持ち、その後Q = [B、C]になります。注AにはBとCへの有向エッジがあり、どちらもQにあるため、これらの値の両方を更新します。

最初の反復

次に、Cを(2 <5)として抽出し、Q = [B]にします。Cは何にも接続されていないため、line16ループは実行されないことに注意してください。

2回目の反復

最後にBを抽出しQはファイですます。注BにはCへの有向エッジがありますが、CはQに存在しないため、再びforループに入ることはありませんline16

3番?

したがって、距離は次のようになります。

変わらない奴ら

AからCへの最短距離は5 + -10 = -5なので、これが間違っていることに注意してくださいaからbからc

したがって、このグラフの場合、ダイクストラのアルゴリズムはAからCまでの距離を誤って計算します。

これは、ダイクストラのアルゴリズムがすでにQから抽出された頂点への短いパスを見つけようとしないために発生します。

どのようなline16ループがやっていることは、頂点に取っているのuをして言ってちょっと我々が行くことができるようになります」Vを介してソースからのu任意のより良い電流よりも、その(ALTまたは代替)で距離distの[V]ので、更新をすることができます場合は、私たちは?ですdist [v] "

line16それらの中で、まだQにあるuのすべての隣接v(つまり、有向枝がuからvに存在する)をチェックすることに注意してください。であれば、彼らはQ. soから訪れたノートを削除し、xがの訪問隣人であるuは、パスがされても、考えられていないソースからの可能な短い方法として、Vline14uからxへのソース

上記の例では、CはBの訪問済みネイバーであるため、パスAからBからCは考慮されず、現在の最短パスはAからC変更されません。

これは、エッジの重みがすべて正の数である場合に実際に役立ちます。これは、短くできないパスを考慮して時間を無駄にしないためです。

したがって、このアルゴリズムを実行するときに、xyの前にQから抽出された場合、パスを見つけることができませんありえない。これを例で説明しましょう。

yは単に抽出され、xは、次いでそれ自体の前に抽出されたDIST [Y]> DIST [X]を、さもなければので、yは前に抽出されていたX。(line 13最初の最小距離)

また、エッジの重みは正、つまりlength(x、y)> 0であるとすでに仮定しました。したがって、yを介した代替距離(alt)は常に大きくなります。つまり、dist [y] + length(x、y)> dist [x]です。したがって、yxへのパスと見なされたとしても、dist [x]の値は更新されなかったため、まだQにあるyの近傍のみを考慮することは理にかなっていると結論付けます(のコメントに注意)line16

しかし、これは、正のエッジ長の仮定に依存します。length (u、v)<0の場合、そのエッジがどれだけ負であるかに応じて、での比較後にdist [x]を置き換えることができline18ます。

したがって、xがすべての頂点v(xがそれらを接続する負のエッジを持つvの近傍であるなど)の前に削除される場合、私たちが行うdist [x]計算は正しくなくなります。

これらのv頂点はそれぞれ、ソースからxへの潜在的な「より良い」パスの最後から2番目の頂点であるため、ダイクストラのアルゴリズムによって破棄されます。

したがって、上記の例では、Bが削除される前にCが削除されたことが原因でした。そのCはBのネガティブエッジを持つ隣人でした!

明確にするために、BとCはAの隣人です。Bには単一のネイバーCがあり、Cにはネイバーがありません。length(a、b)は、頂点aとbの間のエッジの長さです。


2
あなたが言ったように、これを解決するより良い方法は、各比較の後にheapq.heappushメソッドを使用することです。更新された距離をキューに戻します。この状況下では、ダイクストラは負の重みで機能します。私が試したところ、結果は0,5、-5として出てきました
ナンセンス

1
"xからuへのパスソースは考慮されていません"; xからuへのソースを意味しましたか?
slmatrix 2018年

1
@slmatrixそれをキャッチしてくれてありがとう、はい、私はソースからuまでのパスを意味しました。xはuの隣人だからです。
Aditya P

23

ダイクストラのアルゴリズムは、パスが「より重くなる」だけであると想定しているため、重みが3のAからBへのパスと、重みが3のAからCへのパスがある場合、エッジを追加できず、重みが3未満のAからCを介してBに取得します。

この仮定により、負の重みを考慮する必要があるアルゴリズムよりもアルゴリズムが高速になります。


8

ダイクストラのアルゴリズムの正確性:

アルゴリズムの任意のステップに2セットの頂点があります。セットAは、最短パスを計算した頂点から構成されます。セットBは残りの頂点で構成されます。

帰納的仮説:各ステップで、以前のすべての反復が正しいと仮定します。

帰納的ステップ:頂点VをセットAに追加し、距離をdist [V]に設定する場合、この距離が最適であることを証明する必要があります。これが最適でない場合は、頂点Vへのパスが他より短い必要があります。

この別のパスが頂点Xを通過するとします。

ここで、dist [V] <= dist [X]であるため、グラフに負のエッジ長がない限り、Vへのその他のパスは少なくともdist [V]の長さになります。

したがって、ダイクストラのアルゴリズムが機能するには、エッジの重みが負でない必要があります。


6

次のグラフでダイクストラのアルゴリズムを試して、A何が起こっているかを確認します。

グラフ


6
申し訳ありませんが、エラーは発生していません。最初のA->B意志1A->C意志100。その後しB->Dます2。その後しC->Dます-4900。したがって、の値はベルマンフォードD-4900同じになります。これが正しい答えを与えていないのはなぜですか?
Anirban Nag 'tintinmj' 2014

9
@tintinmj Dからの送信エッジがある場合、Dの距離が減少する前にアクセスされ、それ以降は更新されません。これは確かにエラーになります。Dの2を、出力エッジをスキャンした後の最終的な距離と見なすと、このグラフでもエラーが発生します。
クリスチャンシュノール2014

@ tb-久しぶりに聞いてすみませんが、私はここで正しい道を進んでいますか?最初A->Bはに1なりA->Cます100。次にB探索され、に設定さB->D2ます。次に、ソースに戻る最短パスがあるため、Dが探索されますか?もしそうなら、最初に探索されたのだろうと私B->Dは言っても正しいでしょうか?私はあなた以外の人々が与える他のすべての例を理解しています。100C
Pejman Poh 2017

@PejmanPoh私の理解から、B-> Dが100の場合、使用されるHeapStructureでA-> Cが高いため、抽出分は最初にA-> Cを返します。これは、次に見つかった最短パスがパスになることを意味しますCに、その後、-5000であるC-> Dからのパスが明白な選択となり、最短パスはA-> C-> Dからであり、これはかなり確実になると結論付けます。通常の振る舞いである。だから、時には我々は負のサイクルを持っているとき、我々はまだ最短経路の正しい値を取得する可能性がありますが、間違いありません常に、これは我々がしません例..です
T.Dimitrov

1

ダイクストラのアルゴリズムでは、頂点が「閉じている」とマークされている(開いているセットから外れている)ことを思い出してください-頂点から発生したノードはより長い距離につながるため、アルゴリズムはその最短パスを見つけ、このノードを再び開発する必要はありませんが、負の重みの場合はこれは当てはまりません。


0

これまでの他の回答は、ダイクストラのアルゴリズムがパスの負の重みを処理できない理由をかなりよく示しています。

しかし、問題自体はおそらくパスの重みの誤った理解に基づいています。パスの負の重みが一般にパスファインディングアルゴリズムで許可される場合、停止しない永続的なループが発生します。

このことを考慮:

A  <- 5 ->  B  <- (-1) ->  C <- 5 -> D

AとDの間の最適な経路は何ですか?

すべてのパスファインディングアルゴリズムは、BとCの間で継続的にループする必要があります。これを行うと、パス全体の重みが減少するためです。したがって、接続に負の重みを許可すると、各接続が1回だけ使用されるように制限する場合を除いて、任意のpathfindigアルゴリズムが無効になります。


0

負のサイクルを含まない負のエッジでダイクストラのアルゴリズムを使用できますが、頂点に複数回アクセスできるようにする必要があり、そのバージョンでは高速な時間の複雑さが失われます。

その場合、実際には、通常のキューを持ち、ネガティブエッジを処理できるSPFAアルゴリズムを使用する方がよいことを確認しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.