Zaawansowane algorytmy i struktury danych/Wykład 5: Różnice pomiędzy wersjami
Nie podano opisu zmian |
|||
Linia 71: | Linia 71: | ||
Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytm | Po przypomnieniu czym była relaksacja gotowi jesteśmy na zapisanie algorytm | ||
Bellmana-Forda, a następnie udowodnienie jego poprawności. | 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|algorytm_Bellmana-Forda| | |||
BELLMAN-FORD<math>(G,w,s)</math> | |||
INICJUJ<math>(G,s)</math> | |||
'''for''' <math>i=1</math> '''to''' <math>|V|-1</math> '''do''' | |||
'''for''' każda krawędź <math>(u,v) \in E</math> '''do''' | |||
RELAKSUJ<math>(u,v,w)</math> | |||
'''for''' każda krawędź <math>(u,v) \in E</math> '''do''' | |||
'''if''' '<math>d(v)>d(u) + w(u,v)</math> '''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 <math>O(|V||E|)</math>, co jest łatwo | |||
pokazać gdyż: | |||
* proces inicjacji zajmuje czas <math>O(|V|)</math>, | |||
* w każdym z <math>|V|</math> przebiegów głównej pętli algorytmu | |||
przeglądane są wszystkie krawędzie grafu, co zajmuje czas <math>O(|V||E|)</math>, | |||
* końcowa pętla algorytmu działa w czasie <math>O(|E|</math>. | |||
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||bf_poprawnosc_1| | |||
Niech <math>G = (V,E)</math> będzie grafem skierowanym i niech | |||
funkcja <math>w:E \to \mathcal{R}</math> zadaje wagi krawędzi. Niech | |||
<math>s</math> 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 <math>s</math>, to algorytm poprawnie oblicza | |||
odległości, tzn. na koniec działania algorytmu dla każdego <math>v | |||
\in V</math> wartość <math>d(v)</math> jest odległością w <math>G</math> z | |||
<math>s</math> do <math>v</math>. | |||
}} |
Wersja z 11:43, 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 . 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
i funkcję wagową . Algorytm
Bellmana-Forda wylicza dla zadanego wierzchołka , czy
istnieje w grafie cykl o ujemnej wadze osiągalny z
. Jeżeli taki cykl nie istniej to algorytm oblicza
najkrótsze ścieżki z 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 utrzymujemy wartość będącą górnym ograniczeniem wagi najkrótszej ścieżki ze do . W algorytmie utrzymywać będziemy także dla każdego wierzchołka wskaźnik 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 for każdy wierzchołek do
Ustalone przez tą procedure wartości są dobrymi ograniczeniami
górnymi na odległości.
Relaksacja krawędzi polega na sprawdzeniu, czy przechodząc krawędzią z do , nie otrzymamy krótszej ścieżki z do niż ta dotychczas znaleziona. Jeżeli tak to aktualizowane są także wartości i . W celu relaksacji krawędzi używamy procedury RELAKSUJ.
Algorytm Relaksacja krawędzi
{{{3}}}
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 INICJUJ for to do for każda krawędź do RELAKSUJ for każda krawędź do if ' 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 , co jest łatwo pokazać gdyż:
- proces inicjacji zajmuje czas ,
- w każdym z przebiegów głównej pętli algorytmu
przeglądane są wszystkie krawędzie grafu, co zajmuje czas ,
- końcowa pętla algorytmu działa w czasie .
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 będzie grafem skierowanym i niech funkcja zadaje wagi krawędzi. Niech 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 , to algorytm poprawnie oblicza odległości, tzn. na koniec działania algorytmu dla każdego wartość jest odległością w z do .