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

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


To znaczy, tak jak napisaliśmy powyżej, że każdą krawędzią sieci rezydualnej lub '''krawędzią rezydualną''' może przepuścić przepływ, który jest większy niż 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 <math>E_f</math> są albo krawędziami w <math>E</math>, albo krawędziami o odwróconym kierunku. Jeśli mamy <math>f(u, v) < c(u, v)</math> dla krawędzi <math>(u, v)\to E</math>, to wtedy <math>c_f(u,v) = c(u, v) - f(u, v) > 0</math> i <math>(u, v) \in E_f</math>. Jeśli <math>f(u, v) > 0</math> dla krawędzi <math>(u, v) \in E</math>, to wtedy <math>f (v, u) < 0</math>. W tym przypadku, <math>c_f(v, u) = c(v, u) - f(v, u) > 0</math>, i dlatego <math>(v, u) \in E_f</math>. Jeśli ani <math>(u, v)</math> ani <math>(v, u)</math> nie pojawiają się w pierwotnej sieci, to wówczas <math>c(u, v) = c(v, u) = 0</math> i <math>f(u, v) = f(v, u) = 0</math>, a zatem też <math>c_f(u, v) = c_f(v, u) = 0</math>. Podsumowując, krawędź <math>(u, v)</math> może się pojawić w sieci rezydualnej tylko wtedy, kiedy co najmniej jedna z krawędzi <math>(u, v)</math> i <math>(v, u)</math> jest w pierwotnej sieci. Dlatego też <math>|E_f| \le 2 |E|</math>. Należy zauważyć, że sieć rezydualna <math>G_f</math> jest także siecią przepływową o przepustowości zadanej przez <math>c_f</math>. Następujący lemat pokazuje, jak przepływ w rezydualnej sieci powiązany jest z przepływem w pierwotnej sieci przepływów.
Krawędzie w <math>E_f</math> są albo krawędziami w <math>E</math>, albo krawędziami o odwróconym kierunku. Jeśli mamy <math>f(u, v) < c(u, v)</math> dla krawędzi <math>(u, v)\to E</math>, to wtedy <math>c_f(u,v) = c(u, v) - f(u, v) > 0</math> i <math>(u, v) \in E_f</math>. Jeśli <math>f(u, v) > 0</math> dla krawędzi <math>(u, v) \in E</math>, to wtedy <math>f (v, u) < 0</math>. W tym przypadku, <math>c_f(v, u) = c(v, u) - f(v, u) > 0</math>, i dlatego <math>(v, u) \in E_f</math>. Jeśli ani <math>(u, v)</math> ani <math>(v, u)</math> nie pojawiają się w pierwotnej sieci, to wówczas <math>c(u, v) = c(v, u) = 0</math> i <math>f(u, v) = f(v, u) = 0</math>, a zatem też <math>c_f(u, v) = c_f(v, u) = 0</math>. Podsumowując, krawędź <math>(u, v)</math> może się pojawić w sieci rezydualnej tylko wtedy, kiedy co najmniej jedna z krawędzi <math>(u, v)</math> i <math>(v, u)</math> jest w pierwotnej sieci. Dlatego też <math>|E_f| \le 2 |E|</math>. Należy zauważyć, że sieć rezydualna <math>G_f</math> jest także siecią przepływową o przepustowości zadanej przez <math>c_f</math>. Następujący lemat pokazuje, jak przepływ w rezydualnej sieci powiązany jest z przepływem w pierwotnej sieci przepływów.

Wersja z 21:24, 25 wrz 2006

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:
Parser nie mógł rozpoznać (błąd składni): {\displaystyle \sum_{v\in V} f(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.:

Parser nie mógł rozpoznać (błąd składni): {\displaystyle |f| = \sum_{u \in V) f(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:
f(XY,Z)=f(X,Z)+f(Y,Z)f(XY,Z) i f(Z,XY)=f(Z,X)+f(Z,Y)f(Z,XY).
  1. |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ływów 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 zwiększamy f(u,v) o cf(u,v)=5 jednostek, zanim przekroczymy ograniczenie w przepustowości krawędzi (u,v).

Dla danej sieci G=(V,E) i przepływu f, sieć rezydualna G zaindukowana przez f to Gf=(V,Ef) f), 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 mamy 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 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:
(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).

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:

vV(f+f)(u,v)=vV(f(u,v)+f(u,v))=vVf(u,v)+vVf(u,v)=0+0=0.

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

|f+f|=vV(f+f)(s,v)=vV(f(s,v)+f(s,v))=vVf(s,v)+vVf(s,v)=|f|+|f|.

Ś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 prostą ścieżką 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=600|height=500</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ę Parser nie mógł rozpoznać (błąd składni): {\displaystyle f_p : V × V \to R} równą:

fp(u,v)={cf(p)jeżeli (u,v) jest na p,cf(p)jeżeli (v,u) jest na p,0wprzeciwnymprzypadku.      (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 max-flow min-cut, które za chwilę udowodnimy, pokazuje że przepływ jest maksymalny wtedy i tylko wtedy, kiedy jego siec rezydualna nie zawiera żadnej ścieżki powiększającej. Jednak, aby udowodnić to twierdzenie, musimy wpierw wprowadzić pojęcie przekroju sieci przepływów. 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 minimalna dla wszystkich krawędzi 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=600|height=500</flash>


Należy zaobserwować, że przepływ netto w przekroju może zawierać negatywne 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|.

{{dowod|||3=Zauważmy, że f(Ss,V)=0 z warunku zachowania przepływu, dlatego

{{wzor2|1= 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 na wartość 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.

{{dowod|||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 odgórnie przez przepustowość najmniejszego przekroju w sieci. Twierdzenie o maksymalnym przepływie i minimalnym przekroju, które teraz postawomy i udowadniamy, 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]|twierdzenie_5|3=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ą spełnione:

  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 tS, 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)\to(1): Z wniosku 4 wiemy, że |f|c(S,T) dla wszystkich przekrojów (S,T). Czyli warunek, że |f|=c(S,T) co oznacza, że f jest ścieżką maksymalną.

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)

Działanie tego algorytmu przestawione jest na następującej animacji. <flash>file=Zasd_ilustr_r.swf |width=600|height=500</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_c.swf |width=600|height=500</flash>