logo

Algoritmus Floyda Warshalla

The Floyd-Warshall algoritmus , pojmenované po svých tvůrcích Robert Floyd a Stephen Warshall , je základním algoritmem v informatice a teorii grafů. Slouží k nalezení nejkratších cest mezi všemi dvojicemi uzlů ve váženém grafu. Tento algoritmus je vysoce účinný a dokáže zpracovat grafy s oběma pozitivní a n egativní závaží hran , což z něj činí všestranný nástroj pro řešení široké škály problémů se sítí a konektivitou.

Obsah

Banner Floyd-Warshall-Algorithm



Algoritmus Floyda Warshalla:

The Algoritmus Floyda Warshalla je na rozdíl od algoritmu nejkratší cesty všech párů Dijkstra a Bellman Ford což jsou jednozdrojové algoritmy nejkratší cesty. Tento algoritmus funguje pro oba režírovaný a neorientovaný vážený grafy. Ale nefunguje to pro grafy se zápornými cykly (kde je součet hran v cyklu záporný). Následuje Dynamické programování přístup ke kontrole každé možné cesty procházející každým možným uzlem, aby se vypočítala nejkratší vzdálenost mezi každou dvojicí uzlů.

misi nemožné všechny filmy

Nápad za algoritmem Floyda Warshalla:

Předpokládejme, že máme graf G[][] s V vrcholy z 1 na N . Nyní musíme vyhodnotit a nejkratšíPathMatrix[][] kde s hortestPathMatrix[i][j] představuje nejkratší cestu mezi vrcholy i a j .

Jednoznačně nejkratší cesta mezi nimi i na j bude mít nějaké k počet mezilehlých uzlů. Myšlenkou algoritmu floyd warshall je ošetřit každý vrchol 1 na N jako mezilehlý uzel jeden po druhém.

Následující obrázek ukazuje výše uvedenou optimální vlastnost substruktury v algoritmu floyd warshall:

Algoritmus Floyd Warshall Algorithm:

  • Jako první krok inicializujte matici řešení stejnou jako vstupní matici grafu.
  • Potom aktualizujte matici řešení tím, že všechny vrcholy budete považovat za mezilehlý vrchol.
  • Cílem je vybrat všechny vrcholy jeden po druhém a aktualizovat všechny nejkratší cesty, které zahrnují vybraný vrchol jako mezilehlý vrchol v nejkratší cestě.
  • Když vybereme číslo vrcholu k jako mezilehlý vrchol jsme již uvažovali vrcholy {0, 1, 2, .. k-1} jako mezilehlé vrcholy.
  • Za každý pár (i, j) u zdrojových a cílových vrcholů existují dva možné případy.
    • k není mezilehlý vrchol v nejkratší cestě od i na j . Udržujeme hodnotu dist[i][j] jak to je.
    • k je mezilehlý vrchol v nejkratší cestě od i na j . Aktualizujeme hodnotu dist[i][j] tak jako dist[i][k] + dist[k][j], -li dist[i][j]> dist[i][k] + dist[k][j]

Pseudokód algoritmu Floyda Warshalla:>

Pro k = 0 až n – 1
Pro i = 0 až n – 1
Pro j = 0 až n – 1
Vzdálenost[i, j] = min(Vzdálenost[i, j], Vzdálenost[i, k] + Vzdálenost[k, j])

kde i = zdrojový uzel, j = cílový uzel, k = mezilehlý uzel

Ilustrace Floyd Warshall Algorithm:

Předpokládejme, že máme graf, jak je znázorněno na obrázku:

dryRun1drawio

Krok 1 : Inicializujte matici Vzdálenost[][] pomocí vstupního grafu tak, že Vzdálenost[i][j]= váha hrany od i na j , také Vzdálenost[i][j] = Nekonečno, pokud není žádná hrana z i na j.

step1drawio

Krok 2 : Ošetřit uzel A jako mezilehlý uzel a vypočítat Vzdálenost[][] pro každý pár uzlů {i,j} pomocí vzorce:

odstranění z binárního vyhledávacího stromu

= Vzdálenost[i][j] = minimální (Vzdálenost[i][j], (Vzdálenost od i do A ) + (Vzdálenost od A do j))
= Vzdálenost[i][j] = minimum (Vzdálenost[i][j], Vzdálenost[i][ A ] + Vzdálenost[ A ][j])

step2drawio

Krok 3 : Ošetřit uzel B jako mezilehlý uzel a vypočítat Vzdálenost[][] pro každý pár uzlů {i,j} pomocí vzorce:

= Vzdálenost[i][j] = minimální (Vzdálenost[i][j], (Vzdálenost od i do B ) + (Vzdálenost od B do j))
= Vzdálenost[i][j] = minimum (Vzdálenost[i][j], Vzdálenost[i][ B ] + Vzdálenost[ B ][j])

číslo 1 milion
step3drawio

Krok 4 : Ošetřit uzel C jako mezilehlý uzel a vypočítat Vzdálenost[][] pro každý pár uzlů {i,j} pomocí vzorce:

= Vzdálenost[i][j] = minimální (Vzdálenost[i][j], (Vzdálenost od i do C ) + (Vzdálenost od C do j))
= Vzdálenost[i][j] = minimum (Vzdálenost[i][j], Vzdálenost[i][ C ] + Vzdálenost[ C ][j])

step4dravio

Krok 5 : Ošetřit uzel D jako mezilehlý uzel a vypočítat Vzdálenost[][] pro každý pár uzlů {i,j} pomocí vzorce:

= Vzdálenost[i][j] = minimální (Vzdálenost[i][j], (Vzdálenost od i do D ) + (Vzdálenost od D do j))
= Vzdálenost[i][j] = minimum (Vzdálenost[i][j], Vzdálenost[i][ D ] + Vzdálenost[ D ][j])

step5drawio

Krok 6 : Ošetřit uzel A jako mezilehlý uzel a vypočítat Vzdálenost[][] pro každý pár uzlů {i,j} pomocí vzorce:

řetězec k itn

= Vzdálenost[i][j] = minimální (Vzdálenost[i][j], (Vzdálenost od i do A ) + (Vzdálenost od A do j))
= Vzdálenost[i][j] = minimum (Vzdálenost[i][j], Vzdálenost[i][ A ] + Vzdálenost[ A ][j])

step6drawio

Krok 7 : Protože všechny uzly byly považovány za přechodný uzel, můžeme nyní vrátit aktualizovanou matici Vzdálenost[][] jako naši matici odpovědí.

step7drawio
Doporučený postup Vyzkoušejte!

Níže je uvedena implementace výše uvedeného přístupu:

C++
// C++ Program for Floyd Warshall Algorithm #include  using namespace std; // Number of vertices in the graph #define V 4 /* Define Infinite as a large enough value.This value will be used for vertices not connected to each other */ #define INF 99999 // A function to print the solution matrix void printSolution(int dist[][V]); // Solves the all-pairs shortest path // problem using Floyd Warshall algorithm void floydWarshall(int dist[][V]) {  int i, j, k;  /* Add all vertices one by one to  the set of intermediate vertices.  --->Před začátkem iterace máme nejkratší vzdálenosti mezi všemi páry vrcholů tak, že nejkratší vzdálenosti považují za mezilehlé vrcholy pouze vrcholy v množině {0, 1, 2, .. k-1}.  ----> Po skončení iterace se vertex no. k se přidá k množině mezilehlých vrcholů a množina se stane {0, 1, 2, .. k} */ pro (k = 0; k< V; k++) {  // Pick all vertices as source one by one  for (i = 0; i < V; i++) {  // Pick all vertices as destination for the  // above picked source  for (j = 0; j < V; j++) {  // If vertex k is on the shortest path from  // i to j, then update the value of  // dist[i][j]  if (dist[i][j]>(dist[i][k] + dist[k][j]) && (dist[k][j] != INF && dist[i][k] != INF)) dist[i][j] = dist[i][k] + dist[k][j];  } } } // Tisk matice s nejkratší vzdáleností printSolution(dist); } /* Obslužná funkce pro tisk řešení */ void printSolution(int dist[][V]) { cout<< 'The following matrix shows the shortest '  'distances'  ' between every pair of vertices 
';  for (int i = 0; i < V; i++) {  for (int j = 0; j < V; j++) {  if (dist[i][j] == INF)  cout << 'INF'  << ' ';  else  cout << dist[i][j] << ' ';  }  cout << endl;  } } // Driver's code int main() {  /* Let us create the following weighted graph  10  (0)------->(3) | /| 5 | |  | | 1 |/ |  (1)------->(2) 3 */ int graf[V][V] = { { 0, 5, INF, 10 }, { INF, 0, 3, INF }, { INF, INF, 0, 1 }, { INF, INF, INF, 0 } };  // Volání funkce floydWarshall(graph);  návrat 0; } // Tento kód přispěl Mythri J L>
C
// C Program for Floyd Warshall Algorithm #include  // Number of vertices in the graph #define V 4 /* Define Infinite as a large enough  value. This value will be used  for vertices not connected to each other */ #define INF 99999 // A function to print the solution matrix void printSolution(int dist[][V]); // Solves the all-pairs shortest path // problem using Floyd Warshall algorithm void floydWarshall(int dist[][V]) {  int i, j, k;  /* Add all vertices one by one to  the set of intermediate vertices.  --->Před začátkem iterace máme nejkratší vzdálenosti mezi všemi páry vrcholů tak, že nejkratší vzdálenosti považují za mezilehlé vrcholy pouze vrcholy v množině {0, 1, 2, .. k-1}.  ----> Po skončení iterace se vertex no. k se přidá k množině mezilehlých vrcholů a množina se stane {0, 1, 2, .. k} */ pro (k = 0; k< V; k++) {  // Pick all vertices as source one by one  for (i = 0; i < V; i++) {  // Pick all vertices as destination for the  // above picked source  for (j = 0; j < V; j++) {  // If vertex k is on the shortest path from  // i to j, then update the value of  // dist[i][j]  if (dist[i][k] + dist[k][j] < dist[i][j])  dist[i][j] = dist[i][k] + dist[k][j];  }  }  }  // Print the shortest distance matrix  printSolution(dist); } /* A utility function to print solution */ void printSolution(int dist[][V]) {  printf(  'The following matrix shows the shortest distances'  ' between every pair of vertices 
');  for (int i = 0; i < V; i++) {  for (int j = 0; j < V; j++) {  if (dist[i][j] == INF)  printf('%7s', 'INF');  else  printf('%7d', dist[i][j]);  }  printf('
');  } } // driver's code int main() {  /* Let us create the following weighted graph  10  (0)------->(3) | /| 5 | |  | | 1 |/ |  (1)------->(2) 3 */ int graf[V][V] = { { 0, 5, INF, 10 }, { INF, 0, 3, INF }, { INF, INF, 0, 1 }, { INF, INF, INF, 0 } };  // Volání funkce floydWarshall(graph);  návrat 0; }>
Jáva
// Java program for Floyd Warshall All Pairs Shortest // Path algorithm. import java.io.*; import java.lang.*; import java.util.*; class AllPairShortestPath {  final static int INF = 99999, V = 4;  void floydWarshall(int dist[][])  {  int i, j, k;  /* Add all vertices one by one  to the set of intermediate  vertices.  --->Před začátkem iterace máme nejkratší vzdálenosti mezi všemi páry vrcholů tak, že nejkratší vzdálenosti považují za mezilehlé vrcholy pouze vrcholy v množině {0, 1, 2, .. k-1}.  ----> Po skončení iterace se vertex no. k se přidá k množině mezilehlých vrcholů a množina se stane {0, 1, 2, .. k} */ pro (k = 0; k< V; k++) {  // Pick all vertices as source one by one  for (i = 0; i < V; i++) {  // Pick all vertices as destination for the  // above picked source  for (j = 0; j < V; j++) {  // If vertex k is on the shortest path  // from i to j, then update the value of  // dist[i][j]  if (dist[i][k] + dist[k][j]  < dist[i][j])  dist[i][j]  = dist[i][k] + dist[k][j];  }  }  }  // Print the shortest distance matrix  printSolution(dist);  }  void printSolution(int dist[][])  {  System.out.println(  'The following matrix shows the shortest '  + 'distances between every pair of vertices');  for (int i = 0; i < V; ++i) {  for (int j = 0; j < V; ++j) {  if (dist[i][j] == INF)  System.out.print('INF ');  else  System.out.print(dist[i][j] + ' ');  }  System.out.println();  }  }  // Driver's code  public static void main(String[] args)  {  /* Let us create the following weighted graph  10  (0)------->(3) | /| 5 | |  | | 1 |/ |  (1)------->(2) 3 */ int graf[][] = { { 0, 5, INF, 10 }, { INF, 0, 3, INF }, { INF, INF, 0, 1 }, { INF, INF, INF, 0 } };  AllPairShortestPath a = new AllPairShortestPath();  // Volání funkce a.floydWarshall(graph);  } } // Přispěl Aakash Hasija>
Python3
# Python3 Program for Floyd Warshall Algorithm # Number of vertices in the graph V = 4 # Define infinity as the large # enough value. This value will be # used for vertices not connected to each other INF = 99999 # Solves all pair shortest path # via Floyd Warshall Algorithm def floydWarshall(graph):  ''' dist[][] will be the output   matrix that will finally  have the shortest distances   between every pair of vertices '''  ''' initializing the solution matrix   same as input graph matrix  OR we can say that the initial   values of shortest distances  are based on shortest paths considering no   intermediate vertices ''' dist = list(map(lambda i: list(map(lambda j: j, i)), graph))  ''' Add all vertices one by one   to the set of intermediate  vertices.  --->Před začátkem iterace máme nejkratší vzdálenosti mezi všemi dvojicemi vrcholů tak, že nejkratší vzdálenosti považují za mezilehlé vrcholy pouze vrcholy v množině {0, 1, 2, .. k-1}.  ----> Po skončení iterace se vertex no. k se přidá k množině mezilehlých vrcholů a množina se stane {0, 1, 2, .. k} ''' pro k v rozsahu (V): # vybrat všechny vrcholy jako zdroj jeden po druhém pro i v range(V): # Vyberte všechny vrcholy jako cíl pro # výše vybraný zdroj pro j v rozsahu(V): # Pokud je vrchol k na nejkratší cestě z # i do j, aktualizujte hodnotu dist[i][ j] dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j] ) printSolution(dist) # Obslužná funkce pro tisk řešení def printSolution (dist): print('Následující matice ukazuje nejkratší vzdálenosti mezi každou dvojicí vrcholů') pro i v rozsahu(V): pro j v rozsahu(V): if(dist[i][j] == INF): print('%7s' % ('INF'), end=' ') else: print('%7d	' % (dist[i][j]), end=' ') if j == V-1: print() # Kód řidiče if __name__ == '__main__': ''' 10 (0)------ ->(3) | /| 5 | |  | | 1 |/ |  (1)------->(2) 3 ''' graf = [[0, 5, INF, 10], [INF, 0, 3, INF], [INF, INF, 0 , 1], [INF, INF, INF, 0] ] # Volání funkce floydWarshall(graph) # Tento kód přispěl Mythri J L>
C#
// C# program for Floyd Warshall All // Pairs Shortest Path algorithm. using System; public class AllPairShortestPath {  readonly static int INF = 99999, V = 4;  void floydWarshall(int[, ] graph)  {  int[, ] dist = new int[V, V];  int i, j, k;  // Initialize the solution matrix  // same as input graph matrix  // Or we can say the initial  // values of shortest distances  // are based on shortest paths  // considering no intermediate  // vertex  for (i = 0; i < V; i++) {  for (j = 0; j < V; j++) {  dist[i, j] = graph[i, j];  }  }  /* Add all vertices one by one to  the set of intermediate vertices.  --->Před začátkem iterace máme nejkratší vzdálenosti mezi všemi dvojicemi vrcholů tak, že nejkratší vzdálenosti považují za mezilehlé vrcholy pouze vrcholy v množině {0, 1, 2, .. k-1}.  ---> Po skončení iterace se vertex no. k se přidá k množině mezilehlých vrcholů a množina se stane {0, 1, 2, .. k} */ pro (k = 0; k< V; k++) {  // Pick all vertices as source  // one by one  for (i = 0; i < V; i++) {  // Pick all vertices as destination  // for the above picked source  for (j = 0; j < V; j++) {  // If vertex k is on the shortest  // path from i to j, then update  // the value of dist[i][j]  if (dist[i, k] + dist[k, j]  < dist[i, j]) {  dist[i, j]  = dist[i, k] + dist[k, j];  }  }  }  }  // Print the shortest distance matrix  printSolution(dist);  }  void printSolution(int[, ] dist)  {  Console.WriteLine(  'Following matrix shows the shortest '  + 'distances between every pair of vertices');  for (int i = 0; i < V; ++i) {  for (int j = 0; j < V; ++j) {  if (dist[i, j] == INF) {  Console.Write('INF ');  }  else {  Console.Write(dist[i, j] + ' ');  }  }  Console.WriteLine();  }  }  // Driver's Code  public static void Main(string[] args)  {  /* Let us create the following  weighted graph  10  (0)------->(3) | /| 5 | |  | | 1 |/ |  (1)------->(2) 3 */ int[, ] graf = { { 0, 5, INF, 10 }, { INF, 0, 3, INF }, { INF, INF, 0 , 1 }, { INF, INF, INF, 0 } };  AllPairShortestPath a = new AllPairShortestPath();  // Volání funkce a.floydWarshall(graph);  } } // Autorem tohoto článku je // Abdul Mateen Mohammed>
Javascript
// A JavaScript program for Floyd Warshall All  // Pairs Shortest Path algorithm.  var INF = 99999;  class AllPairShortestPath {  constructor() {  this.V = 4;  }  floydWarshall(graph) {  var dist = Array.from(Array(this.V), () =>new Array(this.V).fill(0));  var i, j, k;  // Inicializujeme matici řešení // stejně jako vstupní grafovou matici // Nebo můžeme říci, že počáteční // hodnoty nejkratších vzdáleností // jsou založeny na nejkratších cestách // bez ohledu na mezilehlý // vrchol pro (i = 0; i< this.V; i++) {  for (j = 0; j < this.V; j++) {  dist[i][j] = graph[i][j];  }  }  /* Add all vertices one by one to  the set of intermediate vertices.  --->Před začátkem iterace máme nejkratší vzdálenosti mezi všemi dvojicemi vrcholů tak, že nejkratší vzdálenosti považují za mezilehlé vrcholy pouze vrcholy v množině {0, 1, 2, .. k-1}.  ---> Po skončení iterace se vertex no. k se přidá k množině mezilehlých vrcholů a množina se stane {0, 1, 2, .. k} */ pro (k = 0; k< this.V; k++) {  // Pick all vertices as source  // one by one  for (i = 0; i < this.V; i++) {  // Pick all vertices as destination  // for the above picked source  for (j = 0; j < this.V; j++) {  // If vertex k is on the shortest  // path from i to j, then update  // the value of dist[i][j]  if (dist[i][k] + dist[k][j] < dist[i][j]) {  dist[i][j] = dist[i][k] + dist[k][j];  }  }  }  }  // Print the shortest distance matrix  this.printSolution(dist);  }  printSolution(dist) {  document.write(  'Following matrix shows the shortest ' +  'distances between every pair of vertices '  );  for (var i = 0; i < this.V; ++i) {  for (var j = 0; j < this.V; ++j) {  if (dist[i][j] == INF) {  document.write(' INF ');  } else {  document.write('  ' + dist[i][j] + ' ');  }  }  document.write(' ');  }  }  }  // Driver Code  /* Let us create the following  weighted graph  10  (0)------->(3) | /| 5 | |  | | 1 |/ |  (1)------->(2) 3 */ var graf = [ [0, 5, INF, 10], [INF, 0, 3, INF], [INF, INF, 0, 1] , [INF, INF, INF, 0], ];  var a = new AllPairShortestPath();  // Vytiskne řešení a.floydWarshall(graph);    // Tento kód přispěl rdtaank.>
PHP
 // PHP Program for Floyd Warshall Algorithm  // Solves the all-pairs shortest path problem // using Floyd Warshall algorithm  function floydWarshall ($graph, $V, $INF) { /* dist[][] will be the output matrix   that will finally have the shortest   distances between every pair of vertices */ $dist = array(array(0,0,0,0), array(0,0,0,0), array(0,0,0,0), array(0,0,0,0)); /* Initialize the solution matrix same   as input graph matrix. Or we can say the   initial values of shortest distances are   based on shortest paths considering no   intermediate vertex. */ for ($i = 0; $i < $V; $i++) for ($j = 0; $j < $V; $j++) $dist[$i][$j] = $graph[$i][$j]; /* Add all vertices one by one to the set   of intermediate vertices.   --->Před začátkem iterace máme nejkratší vzdálenosti mezi všemi páry vrcholů tak, že nejkratší vzdálenosti považují za mezilehlé vrcholy pouze vrcholy v množině {0, 1, 2, .. k-1}.   ----> Po skončení iterace se vertex no. k se přidá k množině mezilehlých vrcholů a množina se stane {0, 1, 2, .. k} */ for ($k = 0; $k< $V; $k++) { // Pick all vertices as source one by one  for ($i = 0; $i < $V; $i++) { // Pick all vertices as destination  // for the above picked source  for ($j = 0; $j < $V; $j++) { // If vertex k is on the shortest path from  // i to j, then update the value of dist[i][j]  if ($dist[$i][$k] + $dist[$k][$j] < $dist[$i][$j]) $dist[$i][$j] = $dist[$i][$k] + $dist[$k][$j]; } } } // Print the shortest distance matrix  printSolution($dist, $V, $INF); } /* A utility function to print solution */ function printSolution($dist, $V, $INF) { echo 'The following matrix shows the ' . 'shortest distances between ' . 'every pair of vertices 
'; for ($i = 0; $i < $V; $i++) { for ($j = 0; $j < $V; $j++) { if ($dist[$i][$j] == $INF) echo 'INF ' ; else echo $dist[$i][$j], ' '; } echo '
'; } } // Drivers' Code // Number of vertices in the graph  $V = 4 ; /* Define Infinite as a large enough  value. This value will be used for vertices not connected to each other */ $INF = 99999 ; /* Let us create the following weighted graph   10  (0)------->(3) | /| 5 | |   | | 1 |/ |  (1)------->(2) 3 */ $graf = pole(pole(0, 5, $INF, 10), pole($INF, 0, 3, $INF), pole($ INF, $INF, 0, 1), pole($INF, $INF, $INF, 0)); // Volání funkce floydWarshall($graph, $V, $INF); // Tento kód přispěl Ryuga ?>>

Výstup
The following matrix shows the shortest distances between every pair of vertices 0 5 8 9 INF 0 3 4 INF INF 0 1 INF INF INF 0>

Analýza složitosti algoritmu Floyd Warshall:

  • Časová náročnost: O(V3), kde V je počet vrcholů v grafu a spustíme tři vnořené smyčky, každou o velikosti V
  • Pomocný prostor: O(V2), k vytvoření 2-D matice za účelem uložení nejkratší vzdálenosti pro každý pár uzlů.

Poznámka : Výše ​​uvedený program tiskne pouze nejkratší vzdálenosti. Řešení můžeme upravit pro tisk nejkratších cest také uložením informací o předchůdci do samostatné 2D matice.

Proč je Floyd-Warshall Algorithm lepší pro husté grafy a ne pro řídké grafy?

Hustý graf : Graf, ve kterém je počet hran výrazně vyšší než počet vrcholů.
Řídký graf : Graf, ve kterém je počet hran velmi nízký.

Bez ohledu na to, kolik hran je v grafu Algoritmus Floyda Warshalla běží na O(V3) časy, proto se nejlépe hodí pro Husté grafy . V případě řídkých grafů Johnsonův algoritmus je vhodnější.

  • Jak detekovat negativní cyklus v grafu pomocí Floyd Warshall Algorithm?
  • Jak se Floyd-warshallův algoritmus liší od Dijkstrova algoritmu?
  • Jak se Floyd-warshallův algoritmus liší od Bellman-Fordova algoritmu?

Skutečné aplikace Floyd-Warshallova algoritmu:

  • V počítačových sítích lze tento algoritmus použít k nalezení nejkratší cesty mezi všemi páry uzlů v síti. Toto se nazývá jako směrování sítě .
  • Konektivita letu V leteckém průmyslu najít nejkratší cestu mezi letišti.
  • GIS ( Geografické informační systémy ) aplikace často zahrnují analýzu prostorových dat, jako jsou silniční sítě, za účelem nalezení nejkratších cest mezi místy.
  • Kleeneův algoritmus což je zobecnění floyd warshall, lze použít k nalezení regulárního výrazu pro regulární jazyk.