Zaawansowane algorytmy i struktury danych/Wykład 9

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania

Abstrakt

Wykład ten poświęcony będzie problemowi znajdowania maksymalnego przepływu w grafie. Zaczniemy od wprowadzenia potrzebnych pojęć, a następnie przestawimy metodę Forda-Fulkersona znajdowania maksymalnego przepływu w grafie.

Podstawowe pojęcia

Siecią przepływową, bądź krótko siecią, nazywamy skierowany graf G=(V,E), w którym z każdą krawędzią (u,v)E wiążemy jej nieujemną przepustowość c(u,v)0. W sieci przepływowej wyróżniamy dwa wierzchołki: źródło oznaczane jako s oraz ujście oznaczane jako t.

Niech G będzie siecią oraz niech c:E+ będzie dla niej funkcją przypisującą przepustowości. Przepływem w G nazwiemy funkcję f:V×V spełniającą następujące właściwości:

  • Dla wszystkich u,vV zachodzi f(u,v)c(u,v) - warunek ten nazywamy warunkiem ograniczenia przepustowości.
  • Dla wszystkich u,vV zachodzi f(u,v)=f(v,u) - jest to warunek skośnej symetrii.
  • Dla wszystkich uV{s,t} żądamy aby zachodził warunek zachowania przepływu:
vVf(u,v)=0.

O wartości f(u,v) mówimy, że jest to wielkość przepływu z u do v. Wartość przepływu f, oznaczamy |f| i definiujemy jako sumaryczną wielkość przepływu wypływającego z s wszystkimi krawędziami, tzn.:

|f|=uVf(s,u).

W problemie maksymalnego przepływu dla danej sieci chcemy znaleźć przepływ o największej wartości.

W dalszej części wykładu używać będziemy następującej notacji sumacyjnej, w której argument funkcji f:XY może być podzbiorem A dziedziny X. W takim wypadku przyjmujemy, że wartością funkcji f jest suma jej wartości dla zbioru A, tzn.:

f(X,Y)=xXyYf(x,y).

Używając tej notacji, możemy zapisać warunek zachowania przepływu dla wierzchołka v jako f(v,V)=0. W poniższym lemacie używamy tej notacji do zapisania podstawowych właściwości przepływu.

Lemat 1

Niech G=(V,E) będzie siecią przepływową oraz f przepływem w niej. Wtedy:
  1. Dla wszystkich XV mamy f(X,X)=0.
  2. Dla wszystkich X,YV mamy f(X,Y)=f(Y,X).
  3. Dla wszystkich X,Y,ZV zachodzi:
    Parser nie mógł rozpoznać (nieznana funkcja „\begin{array}”): {\displaystyle \begin{array}{r@{}c@{}l} f(X \cup Y,Z) &=& f(X,Z) + f(Y,Z) - f(X \cap Y,Z) \mbox{ i } f(Z, X \cup Y)=\\ &=& f(Z,X) + f(Z,Y) - f(Z,X \cap Y). \end{array}}
  4. |f|=f(s,V)=f(V,t).

Dowód tego lematu pozostawiony jest jako Zadanie 1 do tego wykładu.

Sieć rezydualna

Intuicyjnie, dla danej sieci przepływowej G i przepływu f, sieć rezydualna składa się z krawędzi, którymi można przesłać większy przepływ. Bardziej formalnie, przypuśćmy, że mamy sieć przepływową G=(V,E) ze źródłem s i ujściem t oraz niech f będzie przepływem w G. Rozważmy teraz parę wierzchołków u,vV. Ilość dodatkowego przepływu cf(u,v), którą możemy przesłać z u do v, zanim przekroczymy przepustowość c(u,v), wynosi

cf(u,v)=c(u,v)f(u,v).

Na przykład, jeśli c(u,v)=16 i f(u,v)=11, wtedy możemy zwiększyć f(u,v) o cf(u,v)=5 jednostek, zanim przekroczymy ograniczenie przepustowości krawędzi (u,v).

Dla danej sieci G=(V,E) i przepływu f, sieć rezydualna G zaindukowana przez f to graf Gf=(V,Ef), gdzie:

Ef={(u,v)V×V:cf(u,v)>0}.

To znaczy, tak jak napisaliśmy powyżej, że każdą krawędzią sieci rezydualnej lub krawędzią rezydualną można przepuścić przepływ, który jest większy niż 0.

Krawędzie w Ef są albo krawędziami w E, albo krawędziami o odwróconym kierunku. Jeśli zachodzi f(u,v)<c(u,v) dla krawędzi (u,v)E, to wtedy cf(u,v)=c(u,v)f(u,v)>0 i (u,v)Ef. Jeśli f(u,v)>0 dla krawędzi (u,v)E, to wtedy f(v,u)<0. W tym przypadku, cf(v,u)=c(v,u)f(v,u)>0, i dlatego (v,u)Ef. Jeśli ani (u,v) ani (v,u) nie pojawiają się w pierwotnej sieci, to wówczas c(u,v)=c(v,u)=0 i f(u,v)=f(v,u)=0, a zatem też cf(u,v)=cf(v,u)=0. Podsumowując, krawędź (u,v) może się pojawić w sieci rezydualnej tylko wtedy, kiedy co najmniej jedna z krawędzi (u,v) i (v,u) jest w pierwotnej sieci. Dlatego też |Ef|2|E|. Należy zauważyć, że sieć rezydualna Gf jest także siecią przepływową o przepustowości krawędzi zadanej przez cf. Następujący lemat pokazuje, jak przepływ w rezydualnej sieci powiązany jest z przepływem w pierwotnej sieci przepływów.

Lemat 1

Niech G=(V,E) będzie siecią przepływową ze źródłem s i ujściem t i niech f będzie przepływem w G. Niech Gf będzie siecią rezydualną dla G, indukowaną przez f, i niech f będzie przepływem w Gf. Wtedy suma przepływów f+f jest przepływem w G o wartości |f+f|=|f|+|f|.

Dowód

Po pierwsze musimy pokazać, że dla sumy przepływów warunki, symetrii skośnej, ograniczenia przepustowości jak i zachowania przepływu są spełnione. W przypadku symetrii skośnej zauważmy, że dla wszystkich u,vV, mamy:
Parser nie mógł rozpoznać (nieznana funkcja „\begin{array}”): {\displaystyle \begin{array}{r@{}c@{}l} (f + f')(u, v) &=& f(u, v) + f'(u, v) = -f(v, u) - f'(v, u) =\\&=& -(f(v, u) + f'(v, u))= -(f + f')(v, u). \end{array}}

W przypadku ograniczenia przepustowości zauważmy, ze f(u,v)cf(u,v) dla wszystkich u,vV i dlatego:

(f+f)(u,v)=f(u,v)+f(u,v)f(u,v)+(c(u,v)f(u,v))=c(u,v).

W przypadku warunku zachowania przepływu, należy zauważyć, że dla wszystkich uVs,t, mamy:

Parser nie mógł rozpoznać (nieznana funkcja „\begin{array}”): {\displaystyle \begin{array}{r@{}c@{}l}\sum_{v \in V}(f+f')(u,v) &=& \sum_{v \in V}(f(u,v) + f'(u,v)) =\\&=& \sum_{v\in V}f(u,v) + \sum_{v\in V}f(u,v) = 0 + 0 = 0.\end{array}}

Ostatecznie otrzymujemy, że wartość f+f wynosi:

Parser nie mógł rozpoznać (nieznana funkcja „\begin{array}”): {\displaystyle \begin{array}{r@{}c@{}l}|f + f'| &=& \sum_{v \in V}(f + f')(s,v) = \sum_{v \in V}(f(s,v) + f'(s,v)) =\\&=& \sum_{v \in V}f(s,v) + \sum_{v\in V}f'(s,v) = |f| + |f'|.\end{array}}

Ścieżki powiększające

Jeśli dana jest sieć przepływowa G=(V,E) i przepływ f, wówczas ścieżka powiększająca p jest ścieżką prostą z s do t w rezydualnej sieci Gf. Z definicji sieci rezydualnej, każda krawędź (u,v) na ścieżce powiększającej pozwala na przesłanie pewnego dodatkowego przepływu z u do v bez naruszenia ograniczenia przepustowości krawędzi. Znajdowanie ścieżki powiększającej w sieci rezydualnej, a następnie powiększenie przy jej pomocy przepływu zobrazowane jest na następującej animacji.

<flash>file=Zasd_ilustr_l.swf |width=800|height=300</flash>

Najwyższą wartość, o jaką można zwiększyć przepływ przy użyciu ścieżki p, nazywamy rezydualną przepustowością p. Wielkość ta jest dana przez:

cf(p)=min{cf(u,v):(u,v) jest na p}.

Zdefiniujmy tę zmianę przepływu związaną ze ścieżką p jako funkcję fp:V×VR równą:

fp(u,v)={cf(p)jeżeli (u,v) jest na p,cf(p)jeżeli (v,u) jest na p,0w przeciwnym przypadku.      (1)

Wówczas fp jest przepływem w Gf o wartości |fp|=cf(p)>0. Dodając fp do f, otrzymamy kolejny przepływ w G, którego wartość jest bliższa maksimum, co sformułowane jest w tym wniosku.

Wniosek 2

Niech G=(V,E) będzie siecią przepływową, niech f będzie przepływem w G i niech p będzie ścieżką powiększającą w Gf. Niech fp będzie zdefiniowane jak we wzorze 1. Zdefiniujmy funkcję f:V×V jako f=f+fp, wówczas f jest przepływem w G o wartości |f|=|f|+|fp|>|f|.

Przekroje w sieci

Twierdzenie o maksymalnym przepływie i minimalnym przekroju, które za chwilę udowodnimy, pokazuje że przepływ jest maksymalny wtedy i tylko wtedy, kiedy jego sieć rezydualna nie zawiera żadnej ścieżki powiększającej. Jednak, aby udowodnić to twierdzenie, musimy wpierw wprowadzić pojęcie przekroju sieci przepływowej. Przekrój (S,T) sieci przepływowej G=(V,E) jest podziałem V na S i T=VS tak, że sS i tT. Jeśli f jest przepływem, wtedy przepływ netto poprzez przekrój (S,T) jest zdefiniowany jako f(S,T). Przepustowość przekroju (S,T) definiujemy jako c(S,T). Minimalnym przekrojem sieci jest przekrój, którego przepustowość jest najmniejsza ze wszystkich przekrojów w sieci.

Poniższa ilustracja pokazuje przekrój ({s,v1,v2},{v3,v4,t}) w sieci przepływów. Przepływ netto poprzez ten przekrój wynosi: f(v1,v3)+f(v2,v3)+f(v2,v4)=12+(4)+11=19, a jego przepustowość wynosi c(v1,v3)+c(v2,v4)=12+14=26.

<flash>file=Zasd_ilustr_b.swf |width=800|height=250</flash>


Należy zaobserwować, że przepływ netto w przekroju może zawierać negatywny przepływy pomiędzy wierzchołkami, jednakże przepustowość przekroju składa się wyłącznie z nieujemnych wartości. Innymi słowy, przepływ netto poprzez przekrój (S,T) składa się z dodatnich przepływów płynących w dwa kierunki; dodatni przepływ z S do T jest dodawany, podczas gdy dodatni przepływ z T do S jest odejmowany. Z drugiej strony, przepustowość przekroju (S,T) jest obliczana tylko od krawędzi odchodzących z S do T. Krawędzie biegnące z T do S nie są włączone do obliczeń c(S,T). Powyższy lemat pokazuje, że przepływ netto przez jakikolwiek przekrój jest taki sam i równy jest wartości przepływu.

Lemat 3

Nich f będzie przepływem w sieci przepływów G ze źródłem s i ujściem t i niech (S,T) będzie przekrojem w G. Wtedy przepływ netto przez (S,T) wynosi f(S,T)=|f|.

Dowód

Zauważmy, że f(Ss,V)=0 z warunku zachowania przepływu, dlatego:
f(S,T)=f(S,V)f(S,S)=f(s,V)+f(Ss,V)=f(s,V)=|f|.

Jako w wniosek z tego lematu otrzymujemy, że przepustowość przekroju jest graniczeniem wartości przepływu.


Wniosek 4

Wartość dowolnego przepływu f w sieci przepływów G jest ograniczona z góry przez przepustowość dowolnego przekroju w G.

Dowód

3

Niech (S,T) będzie dowolnym przekrojem w G i niech f będzie dowolnym przepływem. Z lematu 3 i warunku ograniczenia przepustowości otrzymujemy:

|f|=f(S,T)=uSvTf(u,v)uSvTc(u,v)=c(S,T)

W szczególności maksymalny przepływ w sieci jest ograniczony od góry przez przepustowość najmniejszego przekroju w sieci. Twierdzenie o maksymalnym przepływie i minimalnym przekroju, które teraz postawimy i udowadnimy, mówi że wartość maksymalnego przepływu jest w rzeczywistości równa przepustowości najmniejszego przekroju.

Twierdzenie 5 [O maksymalnym przepływie i minimalnym przekroju]

Jeśli f jest przepływem w sieci przepływowej G=(V,E) ze źródłem s i ujściem t, wówczas następujące warunki są równoważne:
  1. f jest maksymalnym przepływem w G.
  2. Sieć rezydualna Gf nie zawiera żadnych ścieżek powiększających.
  3. |f|=c(S,T) dla pewnego przekroju (S,T) w G.

Dowód

(1)(2): Załóżmy przez sprzeczność, że f jest maksymalnym przepływem w G, ale że Gf posiada ścieżkę powiększającą p. Wówczas, z wniosku 2, suma przepływów f+fp, gdzie fp jest dane wzorem 1, jest przepływem w G o wartości ściśle większej niż |f|, co jest sprzeczne z założeniem, że f jest przepływem maksymalnym.

(2)(3): Przypuśćmy, że Gf nie posiada żadnej ścieżki powiększającej, to znaczy że Gf nie posiada żadnej ścieżki z s do t. Zdefiniujmy:

S={vV: istnieje ścieżka z s do v w Gf},

oraz:

T=VS.

Podział (S,T) jest przekrojem: oczywiście sS i tT, ponieważ nie ma żadnej ścieżki z s do t w Gf. Dla każdej pary wierzchołków uS i vT, mamy f(u,v)=c(u,v), gdyż w przeciwnym wypadku (u,v)Ef, co umiejscowiłoby v w zbiorze S. Dlatego też, z lematu 3, mamy |f|=f(S,T)=c(S,T).

(3)(1): Z wniosku 4 wiemy, że |f|c(S,T) dla wszystkich przekrojów (S,T). Czyli warunek |f|=c(S,T) oznacza, że f jest przepływem maksymalnym.

Algorytm Forda – Fulkersona

W każdej iteracji metody Forda–Fulkersona odnajdujemy dowolną ścieżkę powiększającą p i zwiększamy przepływ f na każdej krawędzi p o przepustowość rezydualną cf(p). Poniżej zamieszczamy implementacje tej metody.

Algorytm [Forda-Fulkersona] znajduje przepływ maksymalny w grafie G


 FORD-FULKERSON(G=(V,E),s,t)
 1 for każda krawędź (u,v)E do
 2 begin
 3   f(u,v)=0
 4   f(v,u)=0
 5  end
 6  while istnieje ścieżka p z s do t w sieci rezydualnej Gf do
 7  begin
 8    cf(p)=min{cf(u,v):(u,v)p}
 9    for każda krawędź (u,v)p do
 10   begin
 11     f(u,v)=f(u,v)+cf(p)
 12     f(v,u)=f(u,v)
 13   end
 14 end
 15 return f

Działanie tego algorytmu przestawione jest na następującej animacji. <flash>file=Zasd_ilustr_r.swf |width=800|height=300</flash>

Czas działania metody Forda-Fuklersona zależy od wyboru ścieżki powiększającej. Jeżeli będziemy ją wybierać źle, to algorytm wręcz może się nie zakończyć. W przypadku, gdy przepustowości krawędzi są całkowito liczbowe, to łatwo możemy pokazać, że czas działania tego algorytmu wynosi O(E|f*|), gdzie f* jest przepływem maksymalnym w sieci. Jeżeli przepływ f* jest mały, to algorytm ten działa szybko, jednak może się zdarzyć, nawet dla prostego przykładu, że algorytm będzie musiał wykonać f* iteracji. Taki przykład pokazany jest na poniższej animacji.

<flash>file=zasd_ilustr_e.swf |width=800|height=300</flash>