logo

Jak znaleźć najkrótszą ścieżkę od źródła do wszystkich wierzchołków za pomocą algorytmu Dijkstry

Mając graf ważony i wierzchołek źródłowy na wykresie, znajdź najkrótsze ścieżki od źródła do wszystkich pozostałych wierzchołków danego grafu.

Notatka: Dany graf nie zawiera żadnej krawędzi ujemnej.

Przykłady:



Wejście: src = 0, wykres pokazano poniżej.

1-(2)

Wyjście: 0 4 12 19 21 11 9 8 14
Wyjaśnienie: Odległość od 0 do 1 = 4.
Minimalna odległość od 0 do 2 = 12. 0->1->2
Minimalna odległość od 0 do 3 = 19. 0->1->2->3
Minimalna odległość od 0 do 4 = 21. 0->7->6->5->4
Minimalna odległość od 0 do 5 = 11. 0->7->6->5
Minimalna odległość od 0 do 6 = 9. 0->7->6
Minimalna odległość od 0 do 7 = 8. 0->7
Minimalna odległość od 0 do 8 = 14. 0->1->2->8

Zalecana praktyka wdrażania algorytmu Dijkstra Wypróbuj!

Algorytm Dijkstry za pomocą Macierz sąsiedztwa :

Pomysł jest taki, aby wygenerować SPT (drzewo najkrótszych ścieżek) z danym źródłem jako korzeniem. Utrzymuj macierz sąsiedztwa z dwoma zbiorami,

  • jeden zestaw zawiera wierzchołki zawarte w drzewie najkrótszej ścieżki,
  • inny zestaw zawiera wierzchołki, które nie zostały jeszcze uwzględnione w drzewie najkrótszych ścieżek.

Na każdym etapie algorytmu znajdź wierzchołek, który znajduje się w innym zbiorze (jeszcze nieuwzględnionym) i ma minimalną odległość od źródła.

ale pełna forma

Algorytm :

  • Utwórz zestaw sptSet (zestaw drzewa najkrótszej ścieżki), który śledzi wierzchołki zawarte w drzewie najkrótszej ścieżki, tj. których minimalna odległość od źródła jest obliczana i finalizowana. Początkowo ten zbiór jest pusty.
  • Przypisz wartość odległości do wszystkich wierzchołków wykresu wejściowego. Zainicjuj wszystkie wartości odległości jako NIESKOŃCZONY . Przypisz wartość odległości 0 dla wierzchołka źródłowego, tak aby był on wybierany jako pierwszy.
  • Chwila sptSet nie obejmuje wszystkich wierzchołków
    • Wybierz wierzchołek W tego tam nie ma sptSet i ma minimalną wartość odległości.
    • Dołącz Cię do sptSet .
    • Następnie zaktualizuj wartość odległości wszystkich sąsiadujących wierzchołków W .
      • Aby zaktualizować wartości odległości, wykonaj iterację przez wszystkie sąsiednie wierzchołki.
      • Dla każdego sąsiedniego wierzchołka W, jeśli suma wartości odległości W (ze źródła) i waga krawędzi u-w , jest mniejsza niż wartość odległości W , a następnie zaktualizuj wartość odległości W .

Notatka: Używamy tablicy logicznej sptSet[] do reprezentowania zbioru wierzchołków zawartych w SPT . Jeśli wartość sptSet[v] jest prawdą, wówczas wierzchołek v jest zawarty w SPT , inaczej nie. Szyk odległość[] służy do przechowywania wartości najkrótszej odległości wszystkich wierzchołków.

Ilustracja algorytmu Dijkstry :

Aby zrozumieć algorytm Dijkstry, zróbmy wykres i znajdź najkrótszą ścieżkę od źródła do wszystkich węzłów.

Rozważ poniższy wykres i źródło = 0

1-(2)

Krok 1:

Java sortowanie listy tablic
  • Zbiór sptSet jest początkowo pusty, a odległości przypisane do wierzchołków to {0, INF, INF, INF, INF, INF, INF, INF} gdzie INF wskazuje na nieskończoność.
  • Teraz wybierz wierzchołek z minimalną wartością odległości. Wybrano wierzchołek 0, uwzględnij go sptSet . Więc sptSet staje się {0}. Po włączeniu 0 do sptSet , zaktualizuj wartości odległości sąsiadujących wierzchołków.
  • Sąsiadujące wierzchołki 0 to 1 i 7. Wartości odległości 1 i 7 są aktualizowane jako 4 i 8.

Poniższy podgraf przedstawia wierzchołki i ich wartości odległości, pokazane są tylko wierzchołki o skończonych wartościach odległości. Wierzchołki zawarte w SPT są pokazane w zielony kolor.

6


Krok 2:

  • Wybierz wierzchołek z minimalną wartością odległości, który nie jest jeszcze uwzględniony SPT (nie w sptSET ). Wierzchołek 1 jest wybierany i dodawany sptSet .
  • Więc sptSet teraz staje się {0, 1}. Zaktualizuj wartości odległości sąsiednich wierzchołków 1.
  • Wartość odległości wierzchołka 2 staje się 12 .
    4


Krok 3:

  • Wybierz wierzchołek z minimalną wartością odległości, który nie jest jeszcze uwzględniony SPT (nie w sptSET ). Wybrano wierzchołek 7. Więc sptSet teraz staje się {0, 1, 7}.
  • Zaktualizuj wartości odległości sąsiednich wierzchołków 7. Wartość odległości wierzchołków 6 i 8 staje się skończona ( 15 i 9 odpowiednio).
    5


Krok 4:

  • Wybierz wierzchołek z minimalną wartością odległości, który nie jest jeszcze uwzględniony SPT (nie w sptSET ). Wybrano wierzchołek 6. Więc sptSet teraz staje się {0, 1, 7, 6} .
  • Zaktualizuj wartości odległości sąsiednich wierzchołków 6. Wartość odległości wierzchołków 5 i 8 zostanie zaktualizowana.
    3-(1)


Powyższe kroki powtarzamy aż sptSet obejmuje wszystkie wierzchołki danego grafu. Ostatecznie otrzymujemy następujące S najgorętsze drzewo ścieżek (SPT).

2-(2)

Poniżej implementacja powyższego podejścia:

C++
// C++ program for Dijkstra's single source shortest path // algorithm. The program is for adjacency matrix // representation of the graph #include  using namespace std; #include  // Number of vertices in the graph #define V 9 // A utility function to find the vertex with minimum // distance value, from the set of vertices not yet included // in shortest path tree int minDistance(int dist[], bool sptSet[]) {  // Initialize min value  int min = INT_MAX, min_index;  for (int v = 0; v < V; v++)  if (sptSet[v] == false && dist[v] <= min)  min = dist[v], min_index = v;  return min_index; } // A utility function to print the constructed distance // array void printSolution(int dist[]) {  cout << 'Vertex 	 Distance from Source' << endl;  for (int i = 0; i < V; i++)  cout << i << ' 				' << dist[i] << endl; } // Function that implements Dijkstra's single source // shortest path algorithm for a graph represented using // adjacency matrix representation void dijkstra(int graph[V][V], int src) {  int dist[V]; // The output array. dist[i] will hold the  // shortest  // distance from src to i  bool sptSet[V]; // sptSet[i] will be true if vertex i is  // included in shortest  // path tree or shortest distance from src to i is  // finalized  // Initialize all distances as INFINITE and stpSet[] as  // false  for (int i = 0; i < V; i++)  dist[i] = INT_MAX, sptSet[i] = false;  // Distance of source vertex from itself is always 0  dist[src] = 0;  // Find shortest path for all vertices  for (int count = 0; count < V - 1; count++) {  // Pick the minimum distance vertex from the set of  // vertices not yet processed. u is always equal to  // src in the first iteration.  int u = minDistance(dist, sptSet);  // Mark the picked vertex as processed  sptSet[u] = true;  // Update dist value of the adjacent vertices of the  // picked vertex.  for (int v = 0; v < V; v++)  // Update dist[v] only if is not in sptSet,  // there is an edge from u to v, and total  // weight of path from src to v through u is  // smaller than current value of dist[v]  if (!sptSet[v] && graph[u][v]  && dist[u] != INT_MAX  && dist[u] + graph[u][v] < dist[v])  dist[v] = dist[u] + graph[u][v];  }  // print the constructed distance array  printSolution(dist); } // driver's code int main() {  /* Let us create the example graph discussed above */  int graph[V][V] = { { 0, 4, 0, 0, 0, 0, 0, 8, 0 },  { 4, 0, 8, 0, 0, 0, 0, 11, 0 },  { 0, 8, 0, 7, 0, 4, 0, 0, 2 },  { 0, 0, 7, 0, 9, 14, 0, 0, 0 },  { 0, 0, 0, 9, 0, 10, 0, 0, 0 },  { 0, 0, 4, 14, 10, 0, 2, 0, 0 },  { 0, 0, 0, 0, 0, 2, 0, 1, 6 },  { 8, 11, 0, 0, 0, 0, 1, 0, 7 },  { 0, 0, 2, 0, 0, 0, 6, 7, 0 } };  // Function call  dijkstra(graph, 0);  return 0; } // This code is contributed by shivanisinghss2110>
C
// C program for Dijkstra's single source shortest path // algorithm. The program is for adjacency matrix // representation of the graph #include  #include  #include  // Number of vertices in the graph #define V 9 // A utility function to find the vertex with minimum // distance value, from the set of vertices not yet included // in shortest path tree int minDistance(int dist[], bool sptSet[]) {  // Initialize min value  int min = INT_MAX, min_index;  for (int v = 0; v < V; v++)  if (sptSet[v] == false && dist[v] <= min)  min = dist[v], min_index = v;  return min_index; } // A utility function to print the constructed distance // array void printSolution(int dist[]) {  printf('Vertex 		 Distance from Source
');  for (int i = 0; i < V; i++)  printf('%d 				 %d
', i, dist[i]); } // Function that implements Dijkstra's single source // shortest path algorithm for a graph represented using // adjacency matrix representation void dijkstra(int graph[V][V], int src) {  int dist[V]; // The output array. dist[i] will hold the  // shortest  // distance from src to i  bool sptSet[V]; // sptSet[i] will be true if vertex i is  // included in shortest  // path tree or shortest distance from src to i is  // finalized  // Initialize all distances as INFINITE and stpSet[] as  // false  for (int i = 0; i < V; i++)  dist[i] = INT_MAX, sptSet[i] = false;  // Distance of source vertex from itself is always 0  dist[src] = 0;  // Find shortest path for all vertices  for (int count = 0; count < V - 1; count++) {  // Pick the minimum distance vertex from the set of  // vertices not yet processed. u is always equal to  // src in the first iteration.  int u = minDistance(dist, sptSet);  // Mark the picked vertex as processed  sptSet[u] = true;  // Update dist value of the adjacent vertices of the  // picked vertex.  for (int v = 0; v < V; v++)  // Update dist[v] only if is not in sptSet,  // there is an edge from u to v, and total  // weight of path from src to v through u is  // smaller than current value of dist[v]  if (!sptSet[v] && graph[u][v]  && dist[u] != INT_MAX  && dist[u] + graph[u][v] < dist[v])  dist[v] = dist[u] + graph[u][v];  }  // print the constructed distance array  printSolution(dist); } // driver's code int main() {  /* Let us create the example graph discussed above */  int graph[V][V] = { { 0, 4, 0, 0, 0, 0, 0, 8, 0 },  { 4, 0, 8, 0, 0, 0, 0, 11, 0 },  { 0, 8, 0, 7, 0, 4, 0, 0, 2 },  { 0, 0, 7, 0, 9, 14, 0, 0, 0 },  { 0, 0, 0, 9, 0, 10, 0, 0, 0 },  { 0, 0, 4, 14, 10, 0, 2, 0, 0 },  { 0, 0, 0, 0, 0, 2, 0, 1, 6 },  { 8, 11, 0, 0, 0, 0, 1, 0, 7 },  { 0, 0, 2, 0, 0, 0, 6, 7, 0 } };  // Function call  dijkstra(graph, 0);  return 0; }>
Jawa
// A Java program for Dijkstra's single source shortest path // algorithm. The program is for adjacency matrix // representation of the graph import java.io.*; import java.lang.*; import java.util.*; class ShortestPath {  // A utility function to find the vertex with minimum  // distance value, from the set of vertices not yet  // included in shortest path tree  static final int V = 9;  int minDistance(int dist[], Boolean sptSet[])  {  // Initialize min value  int min = Integer.MAX_VALUE, min_index = -1;  for (int v = 0; v < V; v++)  if (sptSet[v] == false && dist[v] <= min) {  min = dist[v];  min_index = v;  }  return min_index;  }  // A utility function to print the constructed distance  // array  void printSolution(int dist[])  {  System.out.println(  'Vertex 		 Distance from Source');  for (int i = 0; i < V; i++)  System.out.println(i + ' 		 ' + dist[i]);  }  // Function that implements Dijkstra's single source  // shortest path algorithm for a graph represented using  // adjacency matrix representation  void dijkstra(int graph[][], int src)  {  int dist[] = new int[V]; // The output array.  // dist[i] will hold  // the shortest distance from src to i  // sptSet[i] will true if vertex i is included in  // shortest path tree or shortest distance from src  // to i is finalized  Boolean sptSet[] = new Boolean[V];  // Initialize all distances as INFINITE and stpSet[]  // as false  for (int i = 0; i < V; i++) {  dist[i] = Integer.MAX_VALUE;  sptSet[i] = false;  }  // Distance of source vertex from itself is always 0  dist[src] = 0;  // Find shortest path for all vertices  for (int count = 0; count < V - 1; count++) {  // Pick the minimum distance vertex from the set  // of vertices not yet processed. u is always  // equal to src in first iteration.  int u = minDistance(dist, sptSet);  // Mark the picked vertex as processed  sptSet[u] = true;  // Update dist value of the adjacent vertices of  // the picked vertex.  for (int v = 0; v < V; v++)  // Update dist[v] only if is not in sptSet,  // there is an edge from u to v, and total  // weight of path from src to v through u is  // smaller than current value of dist[v]  if (!sptSet[v] && graph[u][v] != 0  && dist[u] != Integer.MAX_VALUE  && dist[u] + graph[u][v] < dist[v])  dist[v] = dist[u] + graph[u][v];  }  // print the constructed distance array  printSolution(dist);  }  // Driver's code  public static void main(String[] args)  {  /* Let us create the example graph discussed above  */  int graph[][]  = new int[][] { { 0, 4, 0, 0, 0, 0, 0, 8, 0 },  { 4, 0, 8, 0, 0, 0, 0, 11, 0 },  { 0, 8, 0, 7, 0, 4, 0, 0, 2 },  { 0, 0, 7, 0, 9, 14, 0, 0, 0 },  { 0, 0, 0, 9, 0, 10, 0, 0, 0 },  { 0, 0, 4, 14, 10, 0, 2, 0, 0 },  { 0, 0, 0, 0, 0, 2, 0, 1, 6 },  { 8, 11, 0, 0, 0, 0, 1, 0, 7 },  { 0, 0, 2, 0, 0, 0, 6, 7, 0 } };  ShortestPath t = new ShortestPath();  // Function call  t.dijkstra(graph, 0);  } } // This code is contributed by Aakash Hasija>
Pyton
# Python program for Dijkstra's single # source shortest path algorithm. The program is # for adjacency matrix representation of the graph # Library for INT_MAX import sys class Graph(): def __init__(self, vertices): self.V = vertices self.graph = [[0 for column in range(vertices)] for row in range(vertices)] def printSolution(self, dist): print('Vertex 	Distance from Source') for node in range(self.V): print(node, '	', dist[node]) # A utility function to find the vertex with # minimum distance value, from the set of vertices # not yet included in shortest path tree def minDistance(self, dist, sptSet): # Initialize minimum distance for next node min = sys.maxsize # Search not nearest vertex not in the # shortest path tree for u in range(self.V): if dist[u] < min and sptSet[u] == False: min = dist[u] min_index = u return min_index # Function that implements Dijkstra's single source # shortest path algorithm for a graph represented # using adjacency matrix representation def dijkstra(self, src): dist = [sys.maxsize] * self.V dist[src] = 0 sptSet = [False] * self.V for cout in range(self.V): # Pick the minimum distance vertex from # the set of vertices not yet processed. # x is always equal to src in first iteration x = self.minDistance(dist, sptSet) # Put the minimum distance vertex in the # shortest path tree sptSet[x] = True # Update dist value of the adjacent vertices # of the picked vertex only if the current # distance is greater than new distance and # the vertex in not in the shortest path tree for y in range(self.V): if self.graph[x][y]>0 i sptSet[y] == False i  dist[y]> dist[x] + self.graph[x][y]: dist[y] = dist[x] + self.graph[x][y] self.printSolution(dist) # Kod sterownika if __name__ == '__main__': g = Graph(9) g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0], [4, 0, 8, 0, 0, 0, 0, 11, 0], [0, 8, 0, 7, 0, 4, 0, 0, 2], [0, 0, 7, 0, 9, 14, 0, 0, 0], [0, 0, 0, 9, 0, 10, 0, 0, 0], [0, 0, 4, 14, 10, 0, 2, 0, 0], [0, 0, 0, 0, 0, 2, 0, 1, 6], [8, 11, 0, 0, 0, 0, 1, 0, 7], [0, 0, 2, 0, 0, 0, 6, 7, 0] ] g.dijkstra(0) # Ten kod został napisany przez Divyanshu Mehta i zaktualizowany przez Pranav Singh Sambyal>
C#
// C# program for Dijkstra's single // source shortest path algorithm. // The program is for adjacency matrix // representation of the graph using System; class GFG {  // A utility function to find the  // vertex with minimum distance  // value, from the set of vertices  // not yet included in shortest  // path tree  static int V = 9;  int minDistance(int[] dist, bool[] sptSet)  {  // Initialize min value  int min = int.MaxValue, min_index = -1;  for (int v = 0; v < V; v++)  if (sptSet[v] == false && dist[v] <= min) {  min = dist[v];  min_index = v;  }  return min_index;  }  // A utility function to print  // the constructed distance array  void printSolution(int[] dist)  {  Console.Write('Vertex 		 Distance '  + 'from Source
');  for (int i = 0; i < V; i++)  Console.Write(i + ' 		 ' + dist[i] + '
');  }  // Function that implements Dijkstra's  // single source shortest path algorithm  // for a graph represented using adjacency  // matrix representation  void dijkstra(int[, ] graph, int src)  {  int[] dist  = new int[V]; // The output array. dist[i]  // will hold the shortest  // distance from src to i  // sptSet[i] will true if vertex  // i is included in shortest path  // tree or shortest distance from  // src to i is finalized  bool[] sptSet = new bool[V];  // Initialize all distances as  // INFINITE and stpSet[] as false  for (int i = 0; i < V; i++) {  dist[i] = int.MaxValue;  sptSet[i] = false;  }  // Distance of source vertex  // from itself is always 0  dist[src] = 0;  // Find shortest path for all vertices  for (int count = 0; count < V - 1; count++) {  // Pick the minimum distance vertex  // from the set of vertices not yet  // processed. u is always equal to  // src in first iteration.  int u = minDistance(dist, sptSet);  // Mark the picked vertex as processed  sptSet[u] = true;  // Update dist value of the adjacent  // vertices of the picked vertex.  for (int v = 0; v < V; v++)  // Update dist[v] only if is not in  // sptSet, there is an edge from u  // to v, and total weight of path  // from src to v through u is smaller  // than current value of dist[v]  if (!sptSet[v] && graph[u, v] != 0  && dist[u] != int.MaxValue  && dist[u] + graph[u, v] < dist[v])  dist[v] = dist[u] + graph[u, v];  }  // print the constructed distance array  printSolution(dist);  }  // Driver's Code  public static void Main()  {  /* Let us create the example graph discussed above */  int[, ] graph  = new int[, ] { { 0, 4, 0, 0, 0, 0, 0, 8, 0 },  { 4, 0, 8, 0, 0, 0, 0, 11, 0 },  { 0, 8, 0, 7, 0, 4, 0, 0, 2 },  { 0, 0, 7, 0, 9, 14, 0, 0, 0 },  { 0, 0, 0, 9, 0, 10, 0, 0, 0 },  { 0, 0, 4, 14, 10, 0, 2, 0, 0 },  { 0, 0, 0, 0, 0, 2, 0, 1, 6 },  { 8, 11, 0, 0, 0, 0, 1, 0, 7 },  { 0, 0, 2, 0, 0, 0, 6, 7, 0 } };  GFG t = new GFG();  // Function call  t.dijkstra(graph, 0);  } } // This code is contributed by ChitraNayal>
JavaScript
// A Javascript program for Dijkstra's single  // source shortest path algorithm.  // The program is for adjacency matrix  // representation of the graph  let V = 9; // A utility function to find the  // vertex with minimum distance  // value, from the set of vertices  // not yet included in shortest  // path tree  function minDistance(dist,sptSet) {    // Initialize min value   let min = Number.MAX_VALUE;  let min_index = -1;    for(let v = 0; v < V; v++)  {  if (sptSet[v] == false && dist[v] <= min)   {  min = dist[v];  min_index = v;  }  }  return min_index; } // A utility function to print  // the constructed distance array  function printSolution(dist) {  console.log('Vertex 		 Distance from Source ');  for(let i = 0; i < V; i++)  {  console.log(i + ' 		 ' +   dist[i] + ' ');  } } // Function that implements Dijkstra's  // single source shortest path algorithm  // for a graph represented using adjacency  // matrix representation  function dijkstra(graph, src) {  let dist = new Array(V);  let sptSet = new Array(V);    // Initialize all distances as   // INFINITE and stpSet[] as false   for(let i = 0; i < V; i++)  {  dist[i] = Number.MAX_VALUE;  sptSet[i] = false;  }    // Distance of source vertex   // from itself is always 0   dist[src] = 0;    // Find shortest path for all vertices   for(let count = 0; count < V - 1; count++)  {    // Pick the minimum distance vertex   // from the set of vertices not yet   // processed. u is always equal to   // src in first iteration.   let u = minDistance(dist, sptSet);    // Mark the picked vertex as processed   sptSet[u] = true;    // Update dist value of the adjacent   // vertices of the picked vertex.   for(let v = 0; v < V; v++)  {    // Update dist[v] only if is not in   // sptSet, there is an edge from u   // to v, and total weight of path   // from src to v through u is smaller   // than current value of dist[v]   if (!sptSet[v] && graph[u][v] != 0 &&   dist[u] != Number.MAX_VALUE &&  dist[u] + graph[u][v] < dist[v])  {  dist[v] = dist[u] + graph[u][v];  }  }  }    // Print the constructed distance array  printSolution(dist); } // Driver code let graph = [ [ 0, 4, 0, 0, 0, 0, 0, 8, 0 ],  [ 4, 0, 8, 0, 0, 0, 0, 11, 0 ],  [ 0, 8, 0, 7, 0, 4, 0, 0, 2 ],  [ 0, 0, 7, 0, 9, 14, 0, 0, 0],  [ 0, 0, 0, 9, 0, 10, 0, 0, 0 ],  [ 0, 0, 4, 14, 10, 0, 2, 0, 0],  [ 0, 0, 0, 0, 0, 2, 0, 1, 6 ],  [ 8, 11, 0, 0, 0, 0, 1, 0, 7 ],  [ 0, 0, 2, 0, 0, 0, 6, 7, 0 ] ] dijkstra(graph, 0); // This code is contributed by rag2127>

Wyjście
Vertex Distance from Source 0 0 1 4 2 12 3 19 4 21 5 11 6 9 7 8 8 14>

Złożoność czasowa: O(V2)
Przestrzeń pomocnicza: O(V)

Uwagi:

  • Kod oblicza najkrótszą odległość, ale nie oblicza informacji o ścieżce. Utwórz tablicę nadrzędną, zaktualizuj ją, gdy odległość zostanie zaktualizowana i użyj jej, aby pokazać najkrótszą ścieżkę od źródła do różnych wierzchołków.
  • Czas Złożoność wdrożenia wynosi O(V 2 ) . Jeżeli wejście wykres jest reprezentowany za pomocą listy sąsiedztwa , można go zredukować do O(E * log V) za pomocą sterty binarnej. Proszę zobaczyć Algorytm Dijkstry do reprezentacji listy sąsiedztwa po więcej szczegółów.
  • Algorytm Dijkstry nie działa w przypadku wykresów z cyklami o ujemnych wagach.

Dlaczego algorytmy Dijkstry zawodzą w przypadku wykresów mających ujemne krawędzie?

Problem z wagami ujemnymi wynika z faktu, że algorytm Dijkstry zakłada, że ​​po dodaniu węzła do zbioru odwiedzanych węzłów jego odległość jest sfinalizowana i nie ulegnie zmianie. Jednakże w przypadku wag ujemnych założenie to może prowadzić do błędnych wyników.

np zera

Rozważmy dla przykładu następujący wykres:

Awaria-Dijkstry-w przypadku-krawędzi ujemnych

Na powyższym wykresie A jest węzłem źródłowym pomiędzy krawędziami A Do B I A Do C , A Do B jest mniejszą wagą i Dijkstra przypisuje najkrótszą odległość B jako 2, ale z powodu istnienia ujemnej krawędzi od C Do B , rzeczywista najkrótsza odległość zmniejsza się do 1, czego Dijkstra nie wykrywa.

Notatka: Używamy Algorytm najkrótszej ścieżki Bellmana Forda w przypadku gdy mamy ujemne krawędzie na wykresie.

Algorytm Dijkstry za pomocą Lista sąsiedztwa w O(E logV):

W przypadku algorytmu Dijkstry zawsze zaleca się jego użycie Za każdym razem, gdy zmniejsza się odległość wierzchołka, dodajemy jeszcze jedną instancję wierzchołka w kolejce priorytetowej. Nawet jeśli istnieje wiele instancji, bierzemy pod uwagę tylko instancję z minimalną odległością i ignorujemy inne instancje.

  • Złożoność czasowa pozostaje O(E * logV) ponieważ w kolejce priorytetowej będzie co najwyżej O(E) wierzchołków, a O(logE) jest takie samo jak O(logV)
  • Poniżej implementacja powyższego podejścia:

    C++
    // C++ Program to find Dijkstra's shortest path using // priority_queue in STL #include  using namespace std; #define INF 0x3f3f3f3f // iPair ==>Para całkowita typedef para iPara; // Ta klasa reprezentuje graf skierowany za pomocą // klasy reprezentacji listy sąsiedztwa Graph { int V; // Liczba wierzchołków // W grafie ważonym musimy przechowywać wierzchołki // i parę wag dla każdej listy krawędzi>* przym.; public: Graph(int V); // Konstruktor // funkcja dodająca krawędź do wykresu void addEdge(int u, int v, int w);  // drukuje najkrótszą ścieżkę z s void shortestPath(int s); }; // Przydziela pamięć dla listy sąsiedztwa Graph::Graph(int V) { this->V = V;  adj = nowa lista [V]; } void Graph::addEdge(int u, int v, int w) { adj[u].push_back(make_pair(v, w));  adj[v].push_back(make_pair(u, w)); } // Drukuje najkrótsze ścieżki od src do wszystkich pozostałych wierzchołków void Graph::shortestPath(int src) { // Utwórz kolejkę priorytetową do przechowywania wierzchołków, które // są wstępnie przetwarzane. To dziwna składnia w C++.  // Link poniżej zawiera szczegółowe informacje na temat tej składni // https://www.techcodeview.com priorytet_queue , większy > pq;  // Utwórz wektor odległości i zainicjuj // wszystkie odległości jako wektory nieskończone (INF). odst(V, INF);  // Wstaw źródło do kolejki priorytetowej i zainicjuj // jego odległość jako 0. pq.push(make_pair(0, src));  odległość[źródło] = 0;  /* Zapętlanie do momentu, aż kolejka priorytetowa stanie się pusta (lub nie zostaną sfinalizowane wszystkie odległości) */ while (!pq.empty()) { // Pierwszy wierzchołek pary to minimalna odległość // wierzchołek, wyodrębnij go z kolejki priorytetowej.  // etykieta wierzchołka jest przechowywana w drugiej parze (// należy to zrobić w ten sposób, // aby zachować // posortowaną odległość wierzchołków (odległość musi być pierwszym elementem // w parze) int u = pq.top().sekunda; pq.pop(); // 'i' służy do pobrania wszystkich sąsiadujących wierzchołków // listy wierzchołków>::iterator i;  for (i = adj[u].begin(); i != adj[u].end(); ++i) { // Uzyskaj etykietę wierzchołka i wagę bieżącego // sąsiadującego z u.  int v = (*i).pierwszy;  int waga = (*i).sekunda;  // Jeśli ścieżka od v do u jest krótka.  if (dist[v]> dist[u] + waga) { // Aktualizowanie odległości v dist[v] = dist[u] + waga;  pq.push(make_pair(odległość[v], v));  } } } // Wydrukuj najkrótsze odległości zapisane w dist[] printf('Odległość wierzchołka od źródła
    ');  for (int i = 0; tj< V; ++i)  printf('%d 		 %d
    ', i, dist[i]); } // Driver's code int main() {  // create the graph given in above figure  int V = 9;  Graph g(V);  // making above shown graph  g.addEdge(0, 1, 4);  g.addEdge(0, 7, 8);  g.addEdge(1, 2, 8);  g.addEdge(1, 7, 11);  g.addEdge(2, 3, 7);  g.addEdge(2, 8, 2);  g.addEdge(2, 5, 4);  g.addEdge(3, 4, 9);  g.addEdge(3, 5, 14);  g.addEdge(4, 5, 10);  g.addEdge(5, 6, 2);  g.addEdge(6, 7, 1);  g.addEdge(6, 8, 6);  g.addEdge(7, 8, 7);  // Function call  g.shortestPath(0);  return 0; }>
    Jawa
    import java.util.*; class Graph {  private int V;  private List> przym.;  Wykres(int V) { this.V = V;  adj = nowa ArrayList();  for (int i = 0; tj< V; i++) {  adj.add(new ArrayList());  }  }  void addEdge(int u, int v, int w) {  adj.get(u).add(new iPair(v, w));  adj.get(v).add(new iPair(u, w));  }  void shortestPath(int src) {  PriorityQueue pq = nowa Kolejka Priorytetów(V, Comparator.comparingInt(o -> o.sekunda));  int[] dist = nowy int[V];  Tablice.fill(odległość, liczba całkowita.MAX_VALUE);  pq.add(nowa iPair(0, src));  odległość[źródło] = 0;  while (!pq.isEmpty()) { int u = pq.poll().sekunda;  for (iPair v : adj.get(u)) { if (odległość[v.pierwsza]> odległość[u] + v.sekunda) { odległość[v.pierwsza] = odległość[u] + v.sekunda;  pq.add(new iPair(odległość[pierwsza wersja], pierwsza wersja));  } } } System.out.println('Odległość wierzchołka od źródła');  for (int i = 0; tj< V; i++) {  System.out.println(i + '		' + dist[i]);  }  }  static class iPair {  int first, second;  iPair(int first, int second) {  this.first = first;  this.second = second;  }  } } public class Main {  public static void main(String[] args) {  int V = 9;  Graph g = new Graph(V);  g.addEdge(0, 1, 4);  g.addEdge(0, 7, 8);  g.addEdge(1, 2, 8);  g.addEdge(1, 7, 11);  g.addEdge(2, 3, 7);  g.addEdge(2, 8, 2);  g.addEdge(2, 5, 4);  g.addEdge(3, 4, 9);  g.addEdge(3, 5, 14);  g.addEdge(4, 5, 10);  g.addEdge(5, 6, 2);  g.addEdge(6, 7, 1);  g.addEdge(6, 8, 6);  g.addEdge(7, 8, 7);  g.shortestPath(0);  } }>
    Pyton
    import heapq # iPair ==>Integer Pair iPair = krotka # Ta klasa reprezentuje graf skierowany przy użyciu # klasy reprezentacji listy sąsiedztwa Wykres: def __init__(self, V: int): # Konstruktor self.V = V self.adj = [[] for _ in range(V )] def addEdge(self, u: int, v: int, w: int): self.adj[u].append((v, w)) self.adj[v].append((u, w)) # Drukuje najkrótsze ścieżki od src do wszystkich pozostałych wierzchołków def shortestPath(self, src: int): # Utwórz kolejkę priorytetową do przechowywania wierzchołków, które # są wstępnie przetwarzane pq = [] heapq.heappush(pq, (0, src)) # Utwórz wektor dla odległości i zainicjuj wszystkie # odległości jako nieskończone (INF) dist = [float('inf')] * self.V dist[src] = 0 while pq: # Pierwszy wierzchołek pary to minimalna odległość # wierzchołek, wyodrębnij go z kolejki priorytetowej. # etykieta wierzchołka jest przechowywana w drugiej parze d, u = heapq.heappop(pq) # 'i' służy do pobrania wszystkich sąsiednich wierzchołków # wierzchołka dla v, waga w self.adj[u]: # If jest krótka droga do v przez ciebie. if dist[v]> dist[u] + waga: # Aktualizacja odległości v dist[v] = dist[u] + waga heapq.heappush(pq, (dist[v], v)) # Wydrukuj najkrótsze odległości zapisane w dist[] dla i w zakresie(self.V): print(f'{i} 		 {dist[i]}') # Kod sterownika if __name__ == '__main__': # utwórz wykres pokazany na powyższym rysunku V = 9 g = Graph(V) # utwórz pokazany powyżej wykres g.addEdge(0, 1, 4) g.addEdge(0, 7, 8) g.addEdge(1, 2, 8) g.addEdge(1, 7, 11) g.addEdge(2, 3, 7) g.addEdge(2, 8, 2) g.addEdge(2, 5, 4) g.addEdge(3, 4, 9) g.addEdge(3, 5, 14) g.addEdge(4, 5, 10) g.addEdge(5, 6, 2) g.addEdge(6, 7, 1) g.addEdge(6, 8, 6) g.addEdge(7, 8, 7) g.shortestPath(0)>
    C#
    using System; using System.Collections.Generic; // This class represents a directed graph using // adjacency list representation public class Graph {  private const int INF = 2147483647;  private int V;  private List [] przym.;  public Graph(int V) { // Liczba wierzchołków this.V = V;  // Na grafie ważonym musimy przechowywać wierzchołki // i parę wag dla każdej krawędzi this.adj = new List [V];  for (int i = 0; tj< V; i++)  {  this.adj[i] = new List ();  } } public void AddEdge(int u, int v, int w) { this.adj[u].Add(new int[] { v, w });  this.adj[v].Add(new int[] { u, w });  } // Drukuje najkrótsze ścieżki od src do wszystkich pozostałych wierzchołków public void ShortestPath(int src) { // Utwórz kolejkę priorytetową do przechowywania wierzchołków, które // są wstępnie przetwarzane.  Posortowany zestaw pq = nowy SortedSet (nowy DistanceComparer());  // Utwórz tablicę odległości i zainicjuj // wszystkie odległości jako nieskończone (INF) int[] dist = new int[V];  for (int i = 0; tj< V; i++)  {  dist[i] = INF;  }  // Insert source itself in priority queue and initialize  // its distance as 0.  pq.Add(new int[] { 0, src });  dist[src] = 0;  /* Looping till priority queue becomes empty (or all  distances are not finalized) */  while (pq.Count>0) { // Pierwszy wierzchołek pary to minimalna odległość // wierzchołek, wyodrębnij go z kolejki priorytetowej.  // etykieta wierzchołka jest przechowywana w drugiej parze (// należy to zrobić w ten sposób, // żeby wierzchołki były posortowane według odległości) int[] minDistVertex = pq.Min;  pq.Usuń(minDistVertex);  int u = minDistVertex[1];  // 'i' służy do pobrania wszystkich sąsiadujących wierzchołków // wierzchołka foreach (int[] adjVertex in this.adj[u]) { // Pobiera etykietę wierzchołka i wagę bieżącego // sąsiadującego z u.  int v = adjWiersz[0];  int waga = adjVertex[1];  // Jeśli istnieje krótsza ścieżka od v do u.  if (dist[v]> dist[u] + waga) { // Aktualizowanie odległości v dist[v] = dist[u] + waga;  pq.Add(new int[] { dist[v], v });  } } } // Wydrukuj najkrótsze odległości zapisane w dist[] Console.WriteLine('Odległość wierzchołka od źródła');  for (int i = 0; tj< V; ++i)  Console.WriteLine(i + '	' + dist[i]);  }  private class DistanceComparer : IComparer { public int Compare(int[] x, int[] y) { if (x[0] == y[0]) { return x[1] - y[1];  } zwróć x[0] - y[0];  } } } public class Program { // Kod sterownika public static void Main() { // utwórz wykres pokazany na powyższym rysunku int V = 9;  Wykres g = nowy wykres(V);  // utworzenie pokazanego powyżej wykresu g.AddEdge(0, 1, 4);  g.AddEdge(0, 7, 8);  g.AddEdge(1, 2, 8);  g.AddEdge(1, 7, 11);  g.AddEdge(2, 3, 7);  g.AddEdge(2, 8, 2);  g.AddEdge(2, 5, 4);  g.AddEdge(3, 4, 9);  g.AddEdge(3, 5, 14);  g.AddEdge(4, 5, 10);  g.AddEdge(5, 6, 2);  g.AddEdge(6, 7, 1);  g.AddEdge(6, 8, 6);  g.AddEdge(7, 8, 7);  g.Najkrótsza ścieżka(0);  } } // ten kod został stworzony przez bhardwajji>
    JavaScript
    // javascript Program to find Dijkstra's shortest path using // priority_queue in STL const INF = 2147483647; // This class represents a directed graph using // adjacency list representation class Graph {    constructor(V){    // No. of vertices  this.V = V;    // In a weighted graph, we need to store vertex  // and weight pair for every edge  this.adj = new Array(V);  for(let i = 0; i < V; i++){  this.adj[i] = new Array();  }  }  addEdge(u, v, w)  {  this.adj[u].push([v, w]);  this.adj[v].push([u, w]);  }  // Prints shortest paths from src to all other vertices  shortestPath(src)  {  // Create a priority queue to store vertices that  // are being preprocessed. This is weird syntax in C++.  // Refer below link for details of this syntax  // https://www.techcodeview.com  let pq = [];  // Create a vector for distances and initialize all  // distances as infinite (INF)  let dist = new Array(V).fill(INF);  // Insert source itself in priority queue and initialize  // its distance as 0.  pq.push([0, src]);  dist[src] = 0;  /* Looping till priority queue becomes empty (or all  distances are not finalized) */  while (pq.length>0) { // Pierwszy wierzchołek pary to minimalna odległość // wierzchołek, wyodrębnij go z kolejki priorytetowej.  // etykieta wierzchołka jest przechowywana w drugiej parze ( // należy to zrobić w ten sposób, // aby zachować // posortowaną odległość wierzchołków (odległość musi być pierwszym elementem // pary) let u = pq[0][1]; pq.shift(); // 'i' służy do pobrania wszystkich sąsiadujących wierzchołków // wierzchołka for(let i = 0; i< this.adj[u].length; i++){    // Get vertex label and weight of current  // adjacent of u.  let v = this.adj[u][i][0];  let weight = this.adj[u][i][1];  // If there is shorted path to v through u.  if (dist[v]>dist[u] + waga) { // Aktualizacja odległości v dist[v] = dist[u] + waga;  pq.push([odległość[v], v]);  pq.sort((a, b) =>{ if(a[0] == b[0]) return a[1] - b[1]; return a[0] - b[0]; });  } } } // Wydrukuj najkrótsze odległości zapisane w dist[] console.log('Odległość wierzchołka od źródła');  dla (niech i = 0; tj< V; ++i)  console.log(i, ' ', dist[i]);  } } // Driver's code // create the graph given in above figure let V = 9; let g = new Graph(V); // making above shown graph g.addEdge(0, 1, 4); g.addEdge(0, 7, 8); g.addEdge(1, 2, 8); g.addEdge(1, 7, 11); g.addEdge(2, 3, 7); g.addEdge(2, 8, 2); g.addEdge(2, 5, 4); g.addEdge(3, 4, 9); g.addEdge(3, 5, 14); g.addEdge(4, 5, 10); g.addEdge(5, 6, 2); g.addEdge(6, 7, 1); g.addEdge(6, 8, 6); g.addEdge(7, 8, 7); // Function call g.shortestPath(0); // The code is contributed by Nidhi goel.>

    Wyjście
    Vertex Distance from Source 0 0 1 4 2 12 3 19 4 21 5 11 6 9 7 8 8 14>

    Złożoność czasowa: O(E * logV), gdzie E jest liczbą krawędzi, a V jest liczbą wierzchołków.
    Przestrzeń pomocnicza: O(V)

    Zastosowania algorytmu Dijkstry:

    • Mapy Google wykorzystuje algorytm Dijkstry, aby pokazać najkrótszą odległość między źródłem a miejscem docelowym.
    • W sieci komputerowe Algorytm Dijkstry stanowi podstawę dla różnych protokołów routingu, takich jak OSPF (Open Shortest Path First) i IS-IS (Intermediate System to Intermediate System).
    • Systemy transportu i zarządzania ruchem wykorzystują algorytm Dijkstry do optymalizacji przepływu ruchu, minimalizowania zatorów i planowania najbardziej efektywnych tras dla pojazdów.
    • Linie lotnicze wykorzystują algorytm Dijkstry do planowania tras lotów, które minimalizują zużycie paliwa i skracają czas podróży.
    • Algorytm Dijkstry jest stosowany w automatyzacji projektowania elektroniki do routingu połączeń w układach scalonych i chipach integracyjnych o bardzo dużej skali (VLSI).

    Bardziej szczegółowe wyjaśnienie można znaleźć w tym artykule Algorytm najkrótszej ścieżki Dijkstry wykorzystujący kolejkę priorytetów STL .