Algorytm Bellmana-Forda służy do wyszukiwania najkrótszych ścieżek w grafie z pewnego wierzchołka do pozostałych. Krawędzie grafu mogą mieć ustalone wagi (również ujemne), ale graf nie może posiadać cykli ujemnych. Nie jest potrzebne dodatkowe sprawdzanie czy algorytm je posiada - na koniec wystarczy pętla w której zostanie określone czy cykle ujemne wystąpiły.
Początkowo dla każdego wierzchołka określamy, że dystans do niego jest nieskończony, a poprzednik nieokreślony z wyjątkiem wierzchołka początkowego dla którego dystans wynosi 0. Następnie należy powtórzyć n - 1 razy aktualizowanie krawędzi, gdzie n to ilość wierzchołków w grafu. Aktualizacja krawędzi polega na sprawdzeniu czy dla danej pary łączonych wierzchołków dla wierzchołka końcowego nie istnieje krótsza ścieżka tj. czy dystans wierzchołka początkowego dodany do wagi krawędzi jest mniejszy niż dystans wierzchołka końcowego. Krawędzi należy rozpatrywać w kolejności alfabetycznej.
W celu sprawdzenia czy w grafie nie ma cykli ujemnych należy dla każdej krawędzi sprawdzić czy dystans wierzchołka końcowego nie jest mniejszy od sumy dystansu wierzchołka początkowego i wagi krawędzi ich łączących. Jeśli istnieje chociaż jedna krawędź dla której nie jest to spełnione to z pewnością występują w tym grafi cykle ujemne.
Dla przykładu na poniższym grafie zostanie wykonany algorytm Bellmana-Forda:
Jako punkt początkowy zostaje wybrany wierzchołek A, więc dla niego na początku dystans wyniesie 0. Krawędzie będą rozpatrywane w następujące kolejności: AB, AC, AD, BD, BE, CE, DC, DE. Aktualizacja krawędzi zostanie wykonana n - 1 = 4 razy.
Pętla | A | B | C | D | E | Komentarz |
---|---|---|---|---|---|---|
- | 0 | - | ∞ | - | ∞ | - | ∞ | - | ∞ | - | Rozpoczynamy przeglądanie krawędzi |
1 | 0 | - | 1 | A (AB) | 2 | A (AC) | 3 | A (AD) | 5 | B (BE) | W nawiasach umieszczono informację, która krawędź zaktualizowała |
2 | 0 | - | 1 | A | 2 | A | 3 | A | 4 | D (DE) | Tylko jeden wierzchołek zaktualizowany |
3 | 0 | - | 1 | A | 2 | A | 3 | A | 4 | D | Brak aktualizacji, nie trzeba wykonywać czwartego kroku |
4 | . | . | . | . | . | Koniec algorytmu |
Teraz dla każdej krawędzi należy sprawdzić czy nie wystąpiły cykle ujemne. W tym przypadku nie jest to możliwe, ponieważ wagi krawędzi są tylko dodatnie. Ostatecznie drzewo najkrótszych krawędzi wygląda następująco:
Funkcja BellmanFord() dla podanego grafu zwróci tablicę danych z których będzie można odczytać dla każdego wierzchołka jego poprzednika oraz dystans (o ile istnieje połączenie). Algorytm nie będzie sprawdzał poprawności danych wejściowych - o tym powinien wiedzieć sam użytkownik. Graf ma zostać przekazany jako macierz. Przykładowo następujący graf:
ma zostać przekazany w programie jako następująca macierz:
W celu przechowania danych utworzony zostaje specjalny typ, który dla wybranego wierzchołka pozwoli przechować jego dystans oraz poprzednika.
Funkcja BellmanFord() dla podanej macierzy szuka drzewa najkrótszych ścieżek od wybranego wierzchołka start. Wynikiem działania funkcji jest tablica, gdzie dla każdego wierzchołka jest określony do niego dystans oraz poprzednik. Dla przypomnienia algorytm nie sprawdza czy graf zawiera cykle ujemne.
(2. - 7.) Przygotuj tablicę do wypełnienia, a następnie (8.) powtarzając n - 1 razy i (9. - 10.) dla każdej krawędzi: (11.) sprawdź czy krawędź istnieje oraz (12.) czy trzeba zaktualizować dystans wierzchołka końcowego. Jeśli tak to (13. - 14.) należy zaktualizować dystans oraz poprzednika. Na koniec (19.) należy zwrócić wyliczoną tablicę.
W celu przetestowania kodu można skorzystać z poniższego fragmentu kodu. Pomocnicza funkcja wypiszDane() pozwala wyświetlić w czytelnej postaci informacje zgromadzone o wierzchołku.