Floyd最短パスアルゴリズム


Floyd-Warshallアルゴリズム
(Floyd-Warshall algorithm)は任意の2点間を解決する最短経路である
アルゴリズム
、有向図を正しく処理できる
あるいは負の重みの最短経路問題であり,図への伝達閉パケットの計算にも用いられる.
1つの図の重み行列により,その2点間の最短経路行列を求めた.
図の重み付き隣接行列A=[a(i,j)]n×nから、n回の更新が再帰的に行われ、すなわち、マトリクスD(0)=Aから、1つの式に従ってマトリクスD(1)が構築される.また同じ式でD(1)からD(2);......;最後に,同じ式を用いてD(n−1)から行列D(n)を構築した.マトリクスD(n)のi行j列要素は、i番頂点からj番頂点までの最短経路長であり、D(n)を図の距離マトリクスと呼ぶとともに、2点間の最短経路を記録するために後続ノードマトリクスpathを導入することもできる.
iとjの間の他のすべての点を1回緩和する(緩和技術)を用いた.従って時間複雑度はO(n^3);
集合中のノードのみを中間ノードとする最短パスの長さにする.
最短経路が点kを通過すると、
最短経路が点kを通らなければ.
だから、.
その状態遷移方程式は以下の通りである:D[i,j]:=min{
D[i,j],D[i,k]+D[k,j]}
map[i,j]はiからjまでの最短距離を表し,Kは窮屈である.
i,jのブレークポイント,D[n,n]の初期値は0であるか,あるいはテーマの意味に従って行うべきである.
もちろん、この道が通っていなければ、D[i,k]という道がないなど、特殊な処理が必要です.
Floyd−Warshallアルゴリズムの時間的複雑度は空間的複雑度である.
Floyd-Warshallアルゴリズムの説明は次のとおりです.
for k  1 to n do
  for i  1 to n do
    for j  1 to n do
      if () then
          ;

ここでは、点から点への代価を表し、∞は2点間に接続がないことを示す.
実際のアルゴリズムでは,空間を節約するために,元の空間で直接反復することができ,空間を2次元に下げることができる.
大まかなコードは次のとおりです.
 for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(ans[k-1][i][k]==   ||ans[k-1][k][j]==   )
                {
                    ans[k][i][j]=ans[k-1][i][j]; //      ,  i j     k        k-1            
                    continue;
                }
                if(ans[k-1][i][j]==   ||ans[k-1][i][k]+ans[k-1][k][j]<ans[k-1][i][j])
                {
                    ans[k][i][j]=ans[k-1][i][k]+ans[k-1][k][j];
                }
                else
                {
                    ans[k][i][j]=ans[k-1][i][j];
                }
            }
        }
    }
はこのような繰り返しを経て、最後のaからbまでの最短経路の結果はans[n][a][b]である.
それと同時に、ans[k-1][i][j]の値によってans[k][i][j]の値を推定すると、すべてのans[k][i][j]の値はans[k-1][i][j]とans[k-1][i][k]+ans[k-1][k][j]との大きさ関係によって決定されるが、同時にans[k][i][k]とans[k][k][j]はans[k][k][j]とans[k][k][j]とans[k][k][j]とans[k-1][k][j]の値と必ず同じであることに気づき、つまり、これらの値は今回の更新によって変化しません.コードを次のように簡略化します.
for(int k=1;k<=n;k++){
    for(int i=1;i<=n;i++){
          for(int j=1;j<=n;j++){
                if(ans[i][k]==   ||ans[k][j]==   ) continue;
                if(ans[i][j]==   ||ans[i][k]+ans[k][j]<ans[i][j])
                  {
                   ans[i][j]=ans[i][k]+ans[k][j];
                  }
           }
     } 
   }
このように本来の空間複雑度O(N 3)はO(N 2)となる.この2つの配列に新しいものと直接載せるたびにOKです.