フロイドアルゴリズム
使用条件
複数のソースの最短経路を見つけることができ、負の重み側を処理できますが、負のループは発生しません。
時間の複雑さ
O(n 3)
説明する
フロイドアルゴリズムは動的計画法を使用しています。
最初に上の写真を観察します。
それについて考えてみましょう。これまでの経験によれば、任意の2点間の距離を短くしたい場合(たとえば、頂点aから頂点bまで)、3番目の点(頂点k)のみを導入してこれを渡すことができます。頂点kをa-> k-> bに転送することにより、頂点aから頂点bへの元の距離を短くすることができます。では、この通過の頂点kは1〜nのどれですか?1点だけでなく、2点以上の場合、転送が短くなることもあります。つまり、a-> k1-> k2b->またはa-> k1-> k2 ...-> k-> i ...- > b。たとえば、上の図の都市4から都市3までの距離e [4] [3](4-> 3)は、もともと12でした。都市1のみを通過する場合(4-> 1-> 3)、距離は11に短縮されます(e [4] [1] + e [1] [3] = 5 + 6 = 11)。実際、City 1からCity 3は、City 2を経由して、City 1からCity 3への距離を短くすることもできます(e [1] [2] + e [2] [3] = 2 + 3 = 5 )。したがって、2つの都市を同時に通過する場合、都市4から都市3までの距離はさらに10に短縮されます。この例を通して、各頂点が他の2つの頂点間の距離を短くする可能性があることがわかりました。では、この質問を一般化しましょう。
3番目のポイントが2つのポイント間を通過できない場合、次のように、これらの都市間の最短距離が初期距離になります。
2点ごとに転送ポイントを設定する場合は、この転送ポイントを使用する前または使用した後に、短いかどうかを確認します。2ポイントと転送ポイントの間の距離は、すでに最短距離です。それは最短の方法でなければなりません。
最も単純で失礼な方法を使用して、開始点、終了点、通過点を列挙するだけで済みます。
状態転送方程式:
d [i] [j] = min(d [i] [k] + d [k] [j]、d [i] [j])
このようにして、フロイドのアルゴリズムのコアコードを簡単に作成できます。
また、「負の重みループ」を含むグラフには最短経路がないため、フロイドアルゴリズムは「負の重みループ」(または「負の重みループ」)を含むグラフを解くことができないことにも注意してください。たとえば、次のグラフには、頂点1から頂点3への最短パスがありません。1-> 2-> 3-> 1-> 2-> 3->…-> 1-> 2-> 3であるため、1->-2> 3などのループが巻かれるたびに、最短パスは最短時間になります1ずつ減少し、最短経路を見つけることはありません。実際、グラフに「負の重みループ」がある場合、このグラフには最短経路はありません。
コアコード
用(K = 1 ; K <= N; K ++)// 列挙通過点 のためには、(私は= 1 ; I <= N; I ++)// 列挙出発点 のために(J = 1 ; J <= N; J ++) // 列挙の終点 d [i] [j] = min(d [i] [k] + d [k] [j]、d [i] [j]);
ダイクストラアルゴリズム
使用条件
単一のソースの最短経路を求めることは、負の重みを処理できません。
時間の複雑さ
O(n 2)
説明する
ダイクストラアルゴリズムは貪欲法を使用し、d [i]は開始点s0からiまでの最短距離を表します。
開始点s0から開始して、s0に最も近い未訪問のポイントiを選択します。これは最小のd [i]です。エッジの重みが正であるため、iに到達するための短いパスはなくなり、貪欲の正確さが保証されます。 。次に、iを中間点として使用し、iを介して到達できる点の最短距離を更新し、貪欲に進み、訪問されていない最も近い点を見つけます。貪欲のn回の後に、アルゴリズムは終了します。
写真を見てください:
この図によると、ダイクストラアルゴリズムはよく理解されているはずです。
コアコード
for(i = 1 ; k <= n; k ++ ) { maxn = 0x7fffffff ; for(j = 1 ; j <= n; j ++) // 最小のd [j] { if(!vis [j ] && d [j] < maxn) { maxn = d [j]; k = i; } } vis [k] = 1 ; for(j = 1 ; j <= n; j ++) // 中間点として、 D [j] if (w [k] [j])kを介して開始点を更新し、他の点に到達する { d [j] =最小{d [k] + w [k] [j]、d [j]}; } }
SPFAアルゴリズム
使用条件
単一のソースの最短経路を見つけ、負の重みエッジを処理できます
時間の複雑さ
スパースグラフの場合、O(km)、kはより小さな定数であり、密度の高いグラフまたは構築されたグリッドグラフの場合、O(n * m)に増加します。
説明する
キューを作成します。最初は、キューには開始点のみがあります。開始点からすべての点までの最短パスを記録するテーブルを作成します(テーブルの初期値には最大値を割り当て、この点からそれ自体へのパスには0を割り当てます)。次に、スラック操作を実行し、キュー内のポイントを使用して、開始ポイントからすべてのポイントへの最短パスを更新します。更新が成功し、更新されたポイントがキューにない場合は、ポイントをキューの最後に追加します。キューが空になるまで実行を繰り返します。
図:
ソースAが最初にチームに入り、ABがリラックスする
A、B、Cに接続されている側を延長してチームに参加し、リラックスします。
BとCがそれぞれ拡張を開始し、Dがチームに参加してリラックスする
Dがチームを離れ、Eがチームに参加してリラックスします。
Eがキューを離れ、キューが空になり、ソースからすべてのポイントへの最短パスが見つかり、A-> Eの最短パスが8である
上記はSPFAアルゴリズムのプロセスです。
コアコード
q.push(s); vis [s] = 1 ; // ソースポイントsはエンキューされ、エンキューとしてマークされます while (q.size()) { u = q.front(); q.pop(); vis [ u] = 0 ; // チームのヘッドを削除し、チーム に参加しないことをマークします(i = head [u]; i; i = next [i]) { v = ver [i]; w = edge [i]; if( dis [u] + w < dis [v]) { dis [v] = dis [u] + w; if(!vis [v]){q.push(v); vis [v] = 1 ;} / /キューにない場合は、エンキューし、エンキューをマークします } } }