私のおすすめ:
最初に Dijkstra を使用してソースから目的地までの最短経路を見つけますが、ソースと目的地の両方から同時に歩きます (移動した目的地からの距離を示すには負の距離の数値を使用します)。距離 (ソースまたは宛先のいずれかから)。逆ノードからの値を持つノードに遭遇すると、そのノードに到達するためのパスが最短になります。
次に、エッジを削除します。エッジが最短パスの一部でない場合は、現在の既知の最短パスを返します
削除されたエッジが最短経路の一部である場合は、削除されたノードのいずれか小さい方よりも大きい (正または負の) 既知の絶対距離で再度検索を実行します。既知の結果に、始点から歩くときは正、終点から壊れたセグメントまで歩くときは負として、既知の最短経路を追加します。その開始点から両方向に検索します。値セット (正または負) を持つノード、または以前の最短パスの一部であったノードにヒットすると、新しい最短パスが見つかります。
これを行う主な利点は次のとおりです。
- 送信元と宛先の両方から歩くので、送信元ノードが端にある場合を除き、全体的により少ないノードをさまよいます。
- 削除されたエッジが以前の最短パスの最初のエッジであったとしても、検索結果全体を放棄するわけではありません。最短の方法で再接続するパスを見つける必要があるだけです。
削除されたノードが既知の最短パスの一部である場合でも、毎回のブルート再計算に対するパフォーマンスはかなりのものになります。
それがどのように機能するかについては、次のグラフを検討してください。
I
/
B---E
/ / H
A D /|
\ / \ / |
C---F--G
A
からを取得したいのでH
、簡単にするために、各エッジの値が 1 であると仮定します (ただし、値は何でもかまいません)。
A から始めます。
I
/
B---E
/ / H
0 D /|
\ / \ / |
C---F--G
ここで、H の値を 0 から開始するように設定します。
I
/
B---E
/ / (0)
0 D / |
\ / \ / |
C---F---G
そして展開:
I
/
1---E
/ / (0)
0 D / |
\ / \ / |
1---F---G
次に、次に低い値を展開します。これは次のようになりますH
。
I
/
1---E
/ / (0)
0 D / |
\ / \ / |
1---(-1)--(-1)
, orのB
前に来るので、任意に選択します(絶対値は同じです):C
F
G
I
/
1---2
/ / (0)
0 D / |
\ / \ / |
1---(-1)--(-1)
次に C
I
/
1---2
/ / (0)
0 2 / |
\ / \ / |
1---2 & (-1)--(-1)
これで、正の値と負の値の両方を認識するノードができたので、両方への距離であることがわかりA
ます。最初に最短のノードを拡張していたので、これは最短のパスである必要があり、したがって、からへH
の最短のパスと言えます。とコストA
H
A->C->F->H
ABS(2)+ABS(-1) = 3
ここで、C->F I / 1---2 / / (0) 0 2 / | という行を削除したとします。\ / \ / | 1 2 & (-1)--(-1)
次に、C と F の小さい方の値 (この場合は 1) を超える絶対値を持つすべての既知の値を削除します。
I
/
1---E
/ / (0)
0 D / |
\ / \ / |
1 (-1)--(-1)
ここで再び前のように展開しますB
。\ / \ / | 1 (-1)--(-1)
それでC
I
/
1---2
/ / (0)
0 2 / |
\ / \ / |
1 (-1)--(-1)
今 F:
I
/
1---2
/ / (0)
0 2&(-2) / |
\ / \ / |
1 (-1)---(-1)
A
したがって、 からへの最短経路H
は A->C->D->F->H であり、コストがかかることがわかります。ABS(2)+ABS(-2) = 4
これは、任意の数のノード、エッジ、およびエッジの重みで機能します。展開するノードがこれ以上ない場合は、「ルートなし」応答を返します。
以前の最短パスにあったノードのノード値をリセットしないことで、さらに最適化できます。そうすることで、単純な性質は失われますが、過度に複雑ではありません。
上記の例では、最初は違いはありませんが、チェーン内A->C
の および他のノードのコストをC
(負として)覚えているため、リンケージを削除すると違いが生じます。
片面ダイクストラを使用して、削除されたエッジの前にロールバックする場合の利点を以下に示します。
I
/
1---E
/ / H
0 D /|
\ / \ / |
1 F--G
次に展開しB
ます。
I
/
1---2
/ / H
0 D /|
\ / \ / |
1 F--G
子:
I
/
1---2
/ / H
0 2 /|
\ / \ / |
1 F--G
D:
I
/
1---2
/ / H
0 2 /|
\ / \ / |
1 3--G
E:
3
/
1---2
/ / H
0 2 /|
\ / \ / |
1 3--G
ふ:
3
/
1---2
/ / 4
0 2 /|
\ / \ / |
1 3--4
次に、パスが現在であり、コストが 4 であると判断しA->C->D->F->H
ます。ここで 5 つの展開ステップを実行する必要があることに注意してください。双方向の方法で必要な 3 つと比較してください。
削除されたエッジがパスの中央に近づくにつれて、双方向のグラフ ウォーキング アルゴリズムを使用して新しいパスを再計算することにより、節約が大幅に改善されます。たとえば 50 個のノードがぶら下がっていて、そこからへH
の経路が 1 つしかない場合を除きますが、これはごくまれなケースであり、通常のネットワークでは起こりそうにありません。ここで、 からへの直接パスは 1 つしかありませんが、 には50 個のエッジが接続されています。A
H
H
A
A
約 200,000 個のエッジがあり、最大 200,000 個のノードがある可能性がある場合、9 個のノードと 11 個のエッジしかない私の例のグラフと比較して、かなりの節約が見られるでしょう。これは、計算時間の大部分がループに費やされる可能性が高いため、ノード展開が最も少ないアルゴリズムを探しているという考えに基づいています。