Zaawansowane algorytmy i struktury danych/Wykład 10: Różnice pomiędzy wersjami
Nie podano opisu zmian |
|||
Linia 1: | Linia 1: | ||
== Abstrakt == | == Abstrakt == | ||
W wykładzie tym przedstawimy trzy algorytmy znajdowania przepływu w grafie. | W wykładzie tym przedstawimy trzy algorytmy znajdowania przepływu w grafie. Pierwszym będzie algorytm Edmondsa-Karpa działający w czasie <math>O(nm^2)</math>. Następnym będzie algorytm Dinica działający w czasie <math>O(n^2 m)</math>, oraz trzecim tak zwany algorytm trzech Hindusów, działający w czasie <math>O(n^3)</math>. Nazwiska tych tytułowych Hindusów to Malhotra, Kumar i Maheshwari. Dwa ostatnie algorytmy oparte będą na konstrukcji przepływów blokujących, które są analogiczną konstrukcją do konstrukcji maksymalnego zbioru rozłącznych ścieżek, której użyliśmy w [[../Wykład 7#algorytm_hopcrofta-karpa|algorytmie Hopcrofta-Karpa]]. | ||
Pierwszym będzie algorytm Edmondsa-Karpa działający w czasie <math>O(nm^2)</math>. Następnym będzie algorytm Dinica działający w czasie <math>O(n^2 m)</math>, oraz trzecim tak zwany algorytm trzech Hindusów, działający w czasie <math>O(n^3)</math>. Nazwiska tych tytułowych Hindusów to Malhotra, Kumar i Maheshwari. Dwa ostatnie algorytmy oparte będą na konstrukcji przepływów blokujących, które są analogiczną konstrukcją do konstrukcji maksymalnego zbioru rozłącznych ścieżek, której użyliśmy w [[../Wykład 7#algorytm_hopcrofta-karpa|algorytmie Hopcrofta-Karpa]]. | |||
== Algorytm Edmonds’a-Karp’a == | == Algorytm Edmonds’a-Karp’a == | ||
Ograniczenie w czasie działania w algorytmie Forda–Fulkersona może zostać poprawione, kiedy jako ścieżkę powiększającą będziemy wybierać zawsze najkrótszą ścieżkę z <math>s</math> do <math>t</math> w sieci rezydualnej, przy założeniu | Ograniczenie w czasie działania w algorytmie Forda–Fulkersona może zostać poprawione, kiedy jako ścieżkę powiększającą będziemy wybierać zawsze najkrótszą ścieżkę z <math>s</math> do <math>t</math> w sieci rezydualnej, przy założeniu jednostkowych długości krawędzi. Teraz udowodnimy, że algorytm Edmonds’a–Karp’a działa w czasie <math>O(nm^2)</math>. W naszej analizie będziemy korzystać z zapisu <math>d_f (u, v)</math> dla odległości z <math>u</math> do <math>v</math> w <math>G_f</math>, przy założenie, że każda krawędź ma jednostkową wagę. | ||
{{lemat|1|lemat_1|3= | {{lemat|1|lemat_1|3= | ||
Jeśli algorytm Edmondsa–Karpa działa w sieci przepływowej <math>G = (V, E)</math> ze źródłem <math>s</math> i ujściem <math>t</math>, to wtedy dla wszystkich wierzchołków <math>v \in V - \{s, t\}</math>, | Jeśli algorytm Edmondsa–Karpa działa w sieci przepływowej <math>G = (V, E)</math> ze źródłem <math>s</math> i ujściem <math>t</math>, to wtedy dla wszystkich wierzchołków <math>v \in V - \{s, t\}</math>, odległość <math>d_f (s, v)</math> w sieci rezydualnej <math>G_f</math> nie maleje. | ||
}} | }} | ||
{{Dowod|||3=Przypuśćmy, że dla pewnego wierzchołka <math>v \in V - \{s, t\}</math> istnieje powiększający przepływ, który powoduje zmniejszenie odległości najkrótszej ścieżki z <math>s</math> do <math>v</math>, a następnie otrzymamy wynik sprzeczny z tym założeniem. Niech <math>f</math> będzie przepływem zaraz przed pierwszym powiększeniem, które skraca długość najkrótszej ścieżki i niech <math>f'</math> będzie przepływem następującym zaraz potem. Niech <math>v</math> będzie wierzchołkiem o minimalnym <math>d_{f'}(s, v)</math>, którego dystans został zmniejszony poprzez to powiększenie tak, że <math>d_{f'}(s, v) < d_f(s, v)</math>. Niech <math>p = s \to u to \v</math> będzie najkrótszą ścieżką <math>s</math> do <math>v</math> | {{Dowod|||3=Przypuśćmy, że dla pewnego wierzchołka <math>v \in V - \{s, t\}</math> istnieje powiększający przepływ, który powoduje zmniejszenie odległości najkrótszej ścieżki z <math>s</math> do <math>v</math>, a następnie otrzymamy wynik sprzeczny z tym założeniem. Niech <math>f</math> będzie przepływem zaraz przed pierwszym powiększeniem, które skraca długość najkrótszej ścieżki i niech <math>f'</math> będzie przepływem następującym zaraz potem. Niech <math>v</math> będzie wierzchołkiem o minimalnym <math>d_{f'}(s, v)</math>, którego dystans został zmniejszony poprzez to powiększenie tak, że <math>d_{f'}(s, v) < d_f(s, v)</math>. Niech <math>p = s \to u to \v</math> będzie najkrótszą ścieżką z <math>s</math> do <math>v</math> w <math>G_{f'}</math>, tak że <math>(u, v) \in E_{f'}</math> oraz: | ||
{{wzor2|1= | {{wzor2|1= | ||
Linia 24: | Linia 23: | ||
}} | }} | ||
Twierdzimy, że <math>(u, v) \notin E_f</math>. Dlaczego? Gdybyśmy mieli <math>(u, v) \in E_f</math>, wówczas | Twierdzimy, że <math>(u, v) \notin E_f</math>. Dlaczego? Gdybyśmy mieli <math>(u, v) \in E_f</math>, wówczas z nierówności trójkąta dla <math>s,v</math> i <math>u</math> oraz powyższych nierówności wynikałoby: | ||
{{wzor2|1= | {{wzor2|1= | ||
Linia 30: | Linia 29: | ||
}} | }} | ||
Co jest sprzeczne z | Co jest sprzeczne z założeniem, że <math>d_{f'}(s, v) < d_f(s, v)</math>. Jak możemy zatem otrzymać <math>(u, v) \notin E_f</math> i <math>(u, v) \in E_{f'}</math>? Powiększeniu przepływu z <math>f</math> do <math>f'</math> powinno także powiększyć przepływ z <math>v</math> do <math>u</math>. Algorytm Edmondsa–Karpa zawsze powiększa przepływ wzdłuż najkrótszych ścieżek i dlatego też najkrótsza ścieżka z <math>s</math> do <math>u</math> w <math>G_f</math> posiada <math>(v, u)</math> jako ostatnią krawędź. Dlatego mamy: | ||
{{wzor2|1= | {{wzor2|1= | ||
Linia 36: | Linia 35: | ||
}} | }} | ||
co jest sprzeczne z | co jest sprzeczne z założeniem, że <math>d_{f'} (s, v) < d_f(s, v)</math>. Wnioskujemy zatem, że założenie, iż taki wierzchołek <math>v</math> istnieje, jest nieprawdziwe. | ||
}} | }} | ||
Następujące twierdzenie ogranicza liczbę iteracji algorytmu Edmondsa–Karpa. | |||
{{twierdzenie|2|twierdzenie_2|3= | {{twierdzenie|2|twierdzenie_2|3= |
Wersja z 10:33, 27 wrz 2006
Abstrakt
W wykładzie tym przedstawimy trzy algorytmy znajdowania przepływu w grafie. Pierwszym będzie algorytm Edmondsa-Karpa działający w czasie . Następnym będzie algorytm Dinica działający w czasie , oraz trzecim tak zwany algorytm trzech Hindusów, działający w czasie . Nazwiska tych tytułowych Hindusów to Malhotra, Kumar i Maheshwari. Dwa ostatnie algorytmy oparte będą na konstrukcji przepływów blokujących, które są analogiczną konstrukcją do konstrukcji maksymalnego zbioru rozłącznych ścieżek, której użyliśmy w algorytmie Hopcrofta-Karpa.
Algorytm Edmonds’a-Karp’a
Ograniczenie w czasie działania w algorytmie Forda–Fulkersona może zostać poprawione, kiedy jako ścieżkę powiększającą będziemy wybierać zawsze najkrótszą ścieżkę z do w sieci rezydualnej, przy założeniu jednostkowych długości krawędzi. Teraz udowodnimy, że algorytm Edmonds’a–Karp’a działa w czasie . W naszej analizie będziemy korzystać z zapisu dla odległości z do w , przy założenie, że każda krawędź ma jednostkową wagę.
Lemat 1
Dowód
Ze względu na sposób wybrania , wiemy że odległość z wierzchołka się nie zmniejszyła, to znaczy:
Twierdzimy, że . Dlaczego? Gdybyśmy mieli , wówczas z nierówności trójkąta dla i oraz powyższych nierówności wynikałoby:
Co jest sprzeczne z założeniem, że . Jak możemy zatem otrzymać i ? Powiększeniu przepływu z do powinno także powiększyć przepływ z do . Algorytm Edmondsa–Karpa zawsze powiększa przepływ wzdłuż najkrótszych ścieżek i dlatego też najkrótsza ścieżka z do w posiada jako ostatnią krawędź. Dlatego mamy:

Następujące twierdzenie ogranicza liczbę iteracji algorytmu Edmondsa–Karpa.
Twierdzenie 2
Dowód
Niech i będą wierzchołkami w połączonymi krawędzią . Ponieważ ścieżki powiększające są krótszymi ścieżkami, kiedy są krytyczne za pierwszym razem, otrzymujemy
Gdy tylko przepływ jest zwiększony, krawędź znika z sieci rezydualnej. Nie może ona się znów pojawić na żadnej innej ścieżce powiększającej dopóki przepływ z do nie będzie zmniejszony, a nastąpi to tylko wtedy, kiedy pojawi się na ścieżce powiększającej. Jeśli jest przepływem w i to zdarzenie ma miejsce, wówczas mamy:
Ponieważ , co wynika z lematu 1, otrzymujemy

Ponieważ każdą iterację algorytmu FORD-FULKERSON można zaimplementować w czasie , to całkowity czas działania algorytmu Edmondsa-Karpa wynosi . W następnych częściach wykładu pokażemy, jak wykorzystując przepływy blokujące poprawić ten wynik do czasu .
Przepływ blokujący
Przepływem blokującym w sieci rezydualnej nazywamy taki przepływ w , że:
- każda ścieżka z do w jest najkrótszą ścieżką w ,
- oraz każda najkrótsza ścieżka w zawiera krawędź nasyconą w .
Zauważ, że jest to definicja, która odpowiada pojęciu maksymalnego zbioru najkrótszych ścieżek powiększających użytemu w Wykładzie 7. Załóżmy na chwilę, że mamy algorytm znajdujący przepływ blokujący. Pokażemy jak go wykorzystać do znalezienia przepływu maksymalnego w algorytmie Dinica. Algorytmy na znajdowanie przepływu blokującego pokażemy w dalszej części tego wykładu.
Algorytm [Dinica] znajduje przepływ maksymalny w grafie
DINIC(G, s, t) 1 2 while istnieje ścieżka od do w do 3 begin 4 znajdź przepływ blokujący w 5 6 end 7 return
Poprawność algorytmu Dinica wynika bezpośrednio z twierdzenia o maksymalnym przepływie i minimalnym przekroju, gdyż po zakończeniu algorytmu nie ma już w sieci ścieżek powiększających. Zastanówmy się teraz, ile razy może zostać wykonana pętla while, czyli innymi słowy ile razy będzie konieczne znajdowanie przepływu blokującego.
Lemat 3
Dowód

Wniosek 4
Znajdowanie przepływu blokującego - Algorytm Dinica
Zanim przejdziemy do algorytmów znajdujących przepływ blokujący, wprowadźmy pojęcie sieci warstwowej. Sieć warstwową dla sieci rezydualnej definiujemy jako graf skierowany o następującym zbiorze krawędzi:
Zauważmy, że wszystkie ścieżki w z do są najkrótszymi ścieżkami. Jeżeli chcemy wyszukać przepływ blokujący, to zauważmy, że robiąc to w sieci warstwowej, będziemy mieli spełniony automatycznie warunek 1. definicji przepływu blokującego. W grafie wszystkie ścieżki są najkrótsze, jednak nie wszystkie ścieżki muszą prowadzić do . Jeżeli usuniemy zawczasu z grafu Parser nie mógł rozpoznać (nieznana funkcja „\oveline”): {\displaystyle \oveline{G}_f} krawędzie, które prowadzą donikąd, to ścieżki z do będziemy mogli wyszukiwać w czasie .
Algorytm [Dinica] znajduje przepływ blokujący w grafie
DINIC-PRZEPŁYW-BLOKUJĄCY(G_f, s, t) 1 2 skonstruuj graf 3 for każdy do 4 liczba krawędzi wychodzących z 5 while do 6 begin 7 znajdź ścieżkę z do w 8 for każda krawędź do 9 begin 10 11 12 if then 13 begin 14 15 if then 16 end 17 end 18 return
Działanie tego algorytmu zobrazowane jest na następującej animacji. <flash>file=Zasd_ilustr_p.swf |width=600|height=500</flash>
Zauważmy, że po zakończeniu działania algorytmu, w grafie nie pozostanie żadna ścieżka z do . Skonstruowany przepływ będzie więc przepływem blokującym.
Główna pętla programu w liniach 5-17 wykonana zostanie co najwyżej razy, bo w każdym jej przebiegu nasycona jest co najmniej jedna krawędź. Pętlę tę można zaimplementować, aby działała w czasie , dlatego całkowity czas działania tej procedury wynosi . Korzystając z Wniosku 4 widzimy, że czas działania algorytmu Dinica wynosi .
Znajdowanie przepływu blokującego - Algorytm trzech Hindusów
W algorytmie tym użyjemy pojęcia przepustowości wierzchołka w sieci , którą definiujemy jako:
W algorytmie trzech Hindusów, który nazywany jest też algorytmem MKM (od nazwisk autorów), będziemy w każdym wykonaniu głównej pętli algorytmu nasycać jeden wierzchołek, przesyłając z niego przepływ do przodu i w pewnym sensie do tyłu. W czasie wykonywania pętli funkcja przestanie spełniać warunek zachowania przepływu, jednak pod koniec ten warunek zostanie przywrócony. Użyjemy tutaj dwóch pomocniczych procedur:
- procedury PRZEŚLIJ(v) - jeżeli do wierzchołka wpływa większy przepływ niż wypływa, to procedura ta przesyła ten nadmiar do przodu w grafie , nasycając po kolei krawędzie wychodzące z ,
- procedury COFNIJ(v) - jeżeli z wierzchołka wypływa więcej niż do niego wpływa, to procedura ta kompensuje ten niedomiar, przesyłając przepływ z wierzchołków, z których istnieją w krawędzie do , nasycając po kolei krawędzie wchodzące do .
Algorytm [Malhotra, Kumar i Maheshwari] znajduje przepływ blokujący w grafie
MKM-PRZEPŁYW-BLOKUJĄCY(G_f, s, t) 1 2 skonstruuj graf 3 while do 4 begin 5 znajdź wierzchołek o najmniejszym 6 prześlij jednostek przepływu krawędziami wychodzącymi z 7 prześlij jednostek przepływu krawędziami wchodzącymi do 8 for każdy do 9 begin 10 PRZEŚLIJ(w) 11 COFNIJ(w) 12 end 13 usuń z grafu poprawiając przepustowości wierzchołków sąsiednich 13 end 15 return
Działanie tego algorytmu zobrazowane jest na następującej animacji. <flash>file=Zasd_ilustr_q.swf |width=600|height=500</flash>
Zauważmy, że ponieważ wybraliśmy wierzchołek o najmniejszej przepustowości, to zawsze w procedurach PRZEŚLIJ i COFNIJ uda nam się przesłać nadmiar bądź zrekompensować niedomiar w wierzchołku.
Zauważmy, że główna pętla procedury może wykonać się co najwyżej razy, ponieważ za każdym razem nasycany jest co najmniej jeden wierzchołek grafu. Policzmy teraz, ile razy łącznie będą nasycane krawędzie w trakcie wykonywania procedur PRZEŚLIJ i COFNIJ. Co najwyżej razy będziemy przesyłać przepływ nasycając krawędzie. Natomiast liczba przesłań nie nasycających krawędzi nie przekroczy , gdyż dla każdego wierzchołka w wykonaniu procedury PRZEŚLIJ i COFNIJ wykonujemy co najwyżej jedno przesłanie nie nasycające, a operacji tych łącznie wykonywanych jest . Czas potrzebny na znalezienie przepływu blokującego wynosi więc . Łącząc ten algorytm z algorytmem Dinica, otrzymujemy algorytm znajdujący maksymalny przepływ w grafie w czasie .