Dijkstra

Popularne na dworze króla Vizimira powiedzonko głosiło, że jeśli Dijkstra twierdzi, że jest południe, a dookoła panują nieprzebite ciemności, należy zacząć niepokoić się o losy słońca.

Jak dobrze wszystkim wiadomo, Dijkstra prawdę Ci powie, lecz pytanie można mu zadać tylko jedno - "Jaka jest, panie hrabio, najkrótsza ścieżka w grafie (skierowanym bądź nie) o nieujemnych wagach?" Niestety, jak to Sigismund (czy też może Edsger?) ma w swym zwyczaju, odpowiedź otrzymujemy w zawiły sposób. Uczonym językiem można by nazwać to niejakim Algorytmem Dijkstry. Więc pozostawiając wstęp przejdźmy do tego dziwnego szyfru…

Podstawowe informacje

Algorytm Dijkstry

  • operuje na grafach ważonych o nieujemnych wagach krawędzi,
  • jest algorytmem zachłannym
  • wynikowa tablica zawiera długości najkrótszych ścieżek z danego źródła do odpowiednich wierzchołków grafu
  • złożoność : naiwna O(V2), kopcowa O(ElogV), hardcorowa - czyli kopiec Fibonacciego O(E+VlogV)

Algorytm

IN :
G(V,E) -> graf (skierowany bądź nie), o V wierzchołkach, E krawędziach
s -> wierzchołek źródłowy
OUT:
d[] -> tablica najkrótszych ścieżek z s do poszczególnych wierzchołków grafu

Zaczynamy od utworzenia tablicy wynikowej d[], w której każdemu elementowi za wyjątkiem źródła przyznajemy wartość teoretycznej nieskończoności, wierzchołkowi s nadajemy wartość '0'. Następnie tworzymy zbiór wierzchołków jeszcze nie przetworzonych Q (najlepiej kolejkę priorytetową, czyli kopiec), za pomocą którego będziemy przeglądać kolejne wierzchołki. Tu właśnie wkracza pazerność (czy też zachłanność) algorytmu dijkstry - najkorzystniejszy jest dla nas wierzchołek o najmniejszym aktualnym koszcie dojścia (czyli minimum z d[]). Jak przetwarzać? Ano, bierzemy sobie takiego delikwenta i porównujemy z sąsiadami - jeżeli koszt dojścia do niego i długość drogi potrzebnej do osiągnięcia sąsiada [ :P ] jest mniejszy niż aktualny koszt sąsiada [ xD ] to poprawiamy koszt dojścia do sąsiada na lepszy. Przetworzonego Pana Wierzchołka ze zbioru wyrzucamy. Powtarzamy tą operację aż do opustoszenia zbioru. Wszystkie najkrótsze ścieżki z wierzchołka s mamy już zapisane w tablicy d[], więc idziemy na pizze :).

Pseudokod

Dijkstra(G,wagi,s):
 
dla każdego wierzchołka v w V[G] wykonaj
  d[v] := nieskończoność                            // inicjalizacja tablicy wynikowej
d[s] := 0                        
Q := V                                            // utworzenie zbioru v nieprzetworzonych
dopóki Q niepuste wykonaj
  u := Zdejmij_Min(Q)                                    // przetwarzanie wierzchołków
  dla każdego wierzchołka v - sąsiada u wykonaj
    jeżeli d[v] > d[u] + waga(u,v) to
      d[v] := d[u] + waga(u,v)
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License