Zaawansowane algorytmy i struktury danych/Wykład 5: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Sank (dyskusja | edycje)
Sank (dyskusja | edycje)
Linia 74: Linia 74:


{{algorytm|Algorytm Bellmana-Forda|algorytm_Bellmana-Forda|
{{algorytm|Algorytm Bellmana-Forda|algorytm_Bellmana-Forda|
  BELLMAN-FORD<math>(G,w,s)</math>
# BELLMAN-FORD<math>(G,w,s)</math>
    INICJUJ<math>(G,s)</math>
INICJUJ<math>(G,s)</math>
    '''for''' <math>i=1</math> '''to''' <math>|V|-1</math> '''do'''
'''for''' <math>i=1</math> '''to''' <math>|V|-1</math> '''do'''
      '''for''' każda krawędź <math>(u,v) \in E</math> '''do'''
#    '''for''' każda krawędź <math>(u,v) \in E</math> '''do'''
        RELAKSUJ<math>(u,v,w)</math>
#      RELAKSUJ<math>(u,v,w)</math>
    '''for''' każda krawędź <math>(u,v) \in E</math> '''do'''
'''for''' każda krawędź <math>(u,v) \in E</math> '''do'''
      '''if''' '<math>d(v)>d(u) + w(u,v)</math> '''then'''
#    '''if''' '<math>d(v)>d(u) + w(u,v)</math> '''then'''
        '''return''' FALSE
#      '''return''' FALSE
    '''return''' TRUE
'''return''' TRUE
}}
}}



Wersja z 11:50, 20 lip 2006

Abstrakt

Pierwsza część tego wykładu poświęcona będzie problemowi obliczania najkrótszych ścieżek w grafie z jednego źródła w przypadku, w którym wagi krawędzi mogą być ujemne. Zaprezentujemy algorytm Bellmana-Forda, który rozwiązuje ten problem w czasie O(|V||E|). W drugiej części zajmiemy się problemem obliczania odległości między wszystkimi parami wierzchołków. Pokażemy związki tego problemu z mnożeniem macierzy.


Algorytm Bellmana-Forda


Algorytm Bellmana-Forda służy do rozwiązania problemu znalezienia najkrótszych ścieżek w grafie, w którym wagi krawędzi mogą być ujemne. W problemie tym mamy dany graf G=(V,E) i funkcję wagową w:E. Algorytm Bellmana-Forda wylicza dla zadanego wierzchołka s, czy istnieje w grafie G cykl o ujemnej wadze osiągalny z s. Jeżeli taki cykl nie istniej to algorytm oblicza najkrótsze ścieżki z s do wszystkich pozostałych wierzchołków wraz z ich wagami.

Relaksacja

Podobnie ja to było w Algorytmie Dijkstry użyjemy metody relaksacji. Metoda ta polega na tym, że w trakcie działania algorytmu dla każdego wierzchołka vV utrzymujemy wartość d(v) będącą górnym ograniczeniem wagi najkrótszej ścieżki ze s do v. W algorytmie utrzymywać będziemy także dla każdego wierzchołka v wskaźnik π(v) wskazujący na poprzedni wierzchołek przez, który prowadzi dotychczas znaleziona najkrótsza ścieżka. Na początku wielkości te inicjujemy przy pomocy następującej procedury:


Algorytm Inicjalizacja algorytmu najkrótszych ścieżek


 INICJALIZUJ(G,s)
   for każdy wierzchołek vV do
     d(v)=
     π(v)=NIL
   d(s)=0


Ustalone przez tą procedure wartości d(v) są dobrymi ograniczeniami górnymi na odległości.

Relaksacja krawędzi (u,v) polega na sprawdzeniu, czy przechodząc krawędzią (u,v) z u do v, nie otrzymamy krótszej ścieżki z s do vniż ta dotychczas znaleziona. Jeżeli tak to aktualizowane są także wartości d(v) i π(v). W celu relaksacji krawędzi (u,v) używamy procedury RELAKSUJ.

Algorytm Relaksacja krawędzi


 RELAKSUJ(u,v,w)
   if d(v)>d(u)+w(u,v) then
     d(v)=d(u)+w(u,v)
     π(v)=u

Algorytm

Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytm Bellmana-Forda, a następnie udowodnienie jego poprawności.

Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytm Bellmana-Forda, a następnie udowodnienie jego poprawności.

Algorytm Algorytm Bellmana-Forda


# BELLMAN-FORD(G,w,s)
#   INICJUJ(G,s)
#   for i=1 to |V|1 do
#     for każda krawędź (u,v)E do
#       RELAKSUJ(u,v,w)
#   for każda krawędź (u,v)E do
#     if 'd(v)>d(u)+w(u,v) then
#       return FALSE
#   return TRUE

Poniższa animacja przedstawia działanie algorytmu dla grafu o pięciu wierzchołkach.

Algorytm ten działa w czasie O(|V||E|), co jest łatwo pokazać gdyż:

  • proces inicjacji zajmuje czas O(|V|),
  • w każdym z |V| przebiegów głównej pętli algorytmu

przeglądane są wszystkie krawędzie grafu, co zajmuje czas O(|V||E|),

  • końcowa pętla algorytmu działa w czasie O(|E|.

Dowód poprawności algorytmu Bellmana-Forda zaczniemy od pokazania, że algorytm działa poprawnie przy założeniu, że w grafie nie ma cykli o ujemnych wagach.

Lemat

Niech G=(V,E) będzie grafem skierowanym i niech funkcja w:E zadaje wagi krawędzi. Niech s będzie wierzchołkiem z którego liczymy odległości algorytmem Bellmana-Forda. Jeżeli w grafie nie ma cykli o ujemnej wadze osiągalnych z s, to algorytm poprawnie oblicza odległości, tzn. na koniec działania algorytmu dla każdego vV wartość d(v) jest odległością w G z s do v.