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

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Sank (dyskusja | edycje)
m Zastępowanie tekstu – „,↵</math>” na „</math>,”
 
(Nie pokazano 13 wersji utworzonych przez 3 użytkowników)
Linia 1: Linia 1:
== Abstrakt ==
== Abstrakt ==


W wykładzie tym skupimy się na problemie znajdowania skojarzeń w dowolnych grafach. Zaczniemy od postawienia twierdzenia Berge'a i udowodnienia jego słabszej wersji. Następnie udowodnimy lemat o ściąganiu cykli. Wykorzystując ten lemat pokażemy algorytmu Edmondsa znajdujący doskonałe skojarzenia w czasie <math>O(n^3)</math>, gdzie <math>n</math> to liczba wierzchołków w grafie. Algorytm ten będzie jednocześnie końcem dowodu twierdzenia Berga.
W wykładzie tym skupimy się na problemie znajdowania maksymalnych skojarzeń w dowolnych grafach. Zaczniemy od postawienia twierdzenia Berge'a i udowodnienia jego części. Następnie przedstawimy i udowodnimy lemat o ściąganiu cykli. Wykorzystamy ten lemat w konstrukcji algorytmu Edmondsa, znajdującego maksymalne skojarzenia w czasie <math>O(|V|^3)</math>. Algorytm ten będzie jednocześnie konstruktywnym dowodem twierdzenia Berga.


== Skojarzenie w grafach dowolnych ==
== Skojarzenie w grafach dowolnych ==


Na poprzednim wykładzie aby pokazać poprawność algorytmu znajdowania doskonałych skojarzeń skorzystaliśmy z twierdzenie Berge'a, które mówiło, że skojarzenie jest maksymalne gdy nie istnieje względem niego ścieżka powiększająca. Tutaj skorzystamy z komplementarnego podejścia, a mianowicie wykorzystamy poniższy lemat. Jednak przed jego sformułowaniem wprowadźmy kilka oznaczeń. Niech <math>c_n(G)</math> oznacza liczbę spójnych składowych grafu <math>G</math> o nieparzystej liczbie wierzchołków.
Na poprzednim wykładzie, aby pokazać poprawność algorytmu znajdowania doskonałych skojarzeń, skorzystaliśmy z twierdzenia Berge'a o ścieżkach powiększających, które mówiło, że skojarzenie jest maksymalne, gdy nie istnieje względem niego ścieżka powiększająca. Tutaj skorzystamy z komplementarnego podejścia, a mianowicie wykorzystamy poniższy lemat. Jednak do jego sformułowania musimy wprowadzić jedno oznaczenie. Niech <math>c_n(G)</math> oznacza liczbę spójnych składowych grafu <math>G</math> o nieparzystej liczbie wierzchołków.


{{lemat|1|lemat_1|3=
{{lemat|1|lemat_1|3=
Dla dowolnego skojarzenia <math>M</math> w grafie <math>G=(V,E)</math> i dowolnego podzbioru wierzchołków <math>X \subsereq V</math> zachodzi.
Dla dowolnego skojarzenia <math>M</math> w grafie <math>G=(V,E)</math> i dowolnego podzbioru wierzchołków <math>X \subseteq V</math> zachodzi
{{wzor|wzor_1|1|3=
{{wzor|wzor_1|1|3=
<math>|M| \le \frac{1}{2}\left(|V| -(c_n(G-X) - |X|)\right) </math>
<math>|M| \le \frac{1}{2}\left(|V| -(c_n(G-X) - |X|)\right)</math>
}}
}}
}}
}}


{{dowod|||3=
{{dowod|||3=
Zauważmy, że jeżeli nieparzystej składowej z grafu <math>G-X</math> nie skojarzymy z wierzchołkiem z <math>X</math>, to pozostanie w niej co najmniej jeden wierzchołek wolny. Ponieważ z <math>c_n(G-X)</math> nieparzystych składowych możemy skojarzyć w ten sposób co najwyżej <math>|X|</math>, to dla dowolnego skojarzenia <math>M</math> w grafie pozostanie co najmniej <math>c_n(G-X) - |X|</math> wierzchołków wolnych. Czyli skojarzonych wierzchołków będzie co najwyżej <math>|V| -(c_n(G-X) - |X|)</math> a co za tym idzie rozmiar <math>M</math> jest ograniczony tak jak we [[#wzor_1|wzorze 1]].
Zauważmy, że jeżeli nieparzystej składowej z grafu <math>G-X</math> nie skojarzymy z wierzchołkiem z <math>X</math>, to pozostanie w niej co najmniej jeden wierzchołek wolny. Ponieważ z <math>c_n(G-X)</math> nieparzystych składowych możemy skojarzyć w ten sposób co najwyżej <math>|X|</math>, to dla dowolnego skojarzenia <math>M</math> w grafie pozostanie co najmniej <math>c_n(G-X) - |X|</math> wierzchołków wolnych. Tak więc skojarzonych wierzchołków będzie co najwyżej <math>|V| -(c_n(G-X) - |X|)</math>, a co za tym idzie, rozmiar <math>M</math> jest ograniczony tak jak we [[#wzor_1|wzorze 1]].
}}
}}


Lemat ten mówi, że w celu udowodnienia, że skojarzenie <math>M</math> jest maksymalne musimy pokazać zbiór <math>X \subseteq V</math> taki, że we [[#wzor_1|wzorze 1]] będzie zachodziła równość. Niestety lemat ten nie mówi, że taki zbiór musi istnieć. Jednak algorytm Edmondsa który za chile przedstawimy, pozwoli na konstrukcje takiego zbioru, a tym samym pozwoli nam na udowodnienie następującej silniejszej wersji [[#lemat_1|Lematu 1]].
Lemat ten mówi, że aby udowodnienić, że skojarzenie <math>M</math> jest maksymalne, musimy pokazać zbiór <math>X \subseteq V</math>, dla którego we [[#wzor_1|wzorze 1]] będzie zachodziła równość. Niestety, lemat ten nie mówi, że taki zbiór musi istnieć. Jednak algorytm Edmondsa, który za chwilę przedstawimy, pozwoli na konstrukcję takiego zbioru, a tym samym pozwoli nam na udowodnienie następującej silniejszej wersji [[#lemat_1|Lematu 1]].


{{twierdzenie|2 [Berge'a]|twierdzenie_2|3=
{{twierdzenie|2 [Twierdzenie Berge'a]|twierdzenie_2|3=
Niech <math>M</math> będzie maksymalnym skojarzeniem w grafie <math>G=(V,E)</math>, wtedy
Niech <math>M</math> będzie maksymalnym skojarzeniem w grafie <math>G=(V,E)</math>, wtedy
{{wzor|wzor_2|2|3=
{{wzor|wzor_2|2|3=
<math>|M| = \min \left\{\frac{1}{2}\left( |V| - (c_0(G-X) - |X|)\right) \big| X\subseteq V(G) \right\}.</math>
<math>|M| = \min_{X\subseteq V} \frac{1}{2}\left( |V| - (c_0(G-X) - |X|)\right)</math>
}}
}}
}}
}}
Linia 29: Linia 29:
== Lemat o ściąganiu cykli ==
== Lemat o ściąganiu cykli ==


Głównym problemem w konstrukcji algorytmu znajdującego maksymalne skojarzenie w grafach dowolnych jest problem znalezienia ścieżek powiększających. Niestety konstrukcja grafu <math>G_M</math> użyta przez nas na poprzednim wykładzie tutaj nie zadziała, ponieważ w grafie do wierzchołka może istnieć naprzemienna ścieżka kończąca się krawędzią skojarzoną i nie skojarzoną. Nie możemy więc po prostu pamiętać, czy wierzchołek został juz odwiedzony i użyć dzięki temu prostego przeszukiwania grafu. W celu poradzenia sobie z takimi trudnymi przypadkami użyjemy następującego lematu.
Głównym problemem w konstrukcji algorytmu, znajdującego maksymalne skojarzenie w grafach dowolnych, jest problem znalezienia ścieżki powiększającej. Niestety, konstrukcja grafu <math>G_M</math> użyta przez nas na poprzednim wykładzie tutaj nie zadziała, ponieważ teraz mogą istnieć naprzemienne ścieżki zaczynające się w wierzchołku wolnym i kończące się krawędzią skojarzoną i nie skojarzoną w wybranym wierzchołku. Nie możemy więc po prostu pamiętać, czy wierzchołek został juz odwiedzony i użyć dzięki temu prostego przeszukiwania grafu. Aby poradzić sobie z takimi trudnymi przypadkami, użyjemy następującego lematu.


{{lemat|3 [O ściąganiu cykli]|lemat_3|3=
{{lemat|3 [O ściąganiu cykli]|lemat_3|3=
Linia 35: Linia 35:
* <math>M</math> będzie skojarzeniem w <math>G</math>,
* <math>M</math> będzie skojarzeniem w <math>G</math>,
* <math>Z</math> będzie cyklem długości <math>2k+1</math> zawierającym <math>k</math> krawędzi z <math>M</math> i rozłącznym z resztą <math>M</math>.
* <math>Z</math> będzie cyklem długości <math>2k+1</math> zawierającym <math>k</math> krawędzi z <math>M</math> i rozłącznym z resztą <math>M</math>.
Skonstruujmy nowy graf <math>G'</math> z <math>G</math> poprzez ściągnięcie <math>Z</math> do jednego wierzchołka. Skojarzenie <math>M' = M-E(Z)</math> jest maksymalne w <math>G'</math> wtedy i tylko wtedy gdy skojarzenie <math>M</math> jest maksymalne w <math>G</math>.
Skonstruujmy nowy graf <math>G'</math> z <math>G</math> poprzez ściągnięcie <math>Z</math> do jednego wierzchołka. Skojarzenie <math>M' = M-E(Z)</math> jest maksymalne w <math>G'</math> wtedy i tylko wtedy, gdy skojarzenie <math>M</math> jest maksymalne w <math>G</math>.
}}
}}


{{dowod|||3=
{{dowod|||3=
Udowodnijmy najpierw, że jeżeli <math>M'</math> jest skojarzeniem maksymalnym to także <math>M</math> jest maksymalne. Załóżmy przeciwnie, że <math>M</math> nie jest maksymalnym skojarzeniem w G. Wtedy istnieje ścieżka powiększająca <math>P</math> względem <math>M</math>. Jeżeli <math>P</math> jest rozłączna z <math>Z</math>, to <math>P</math> także jest ścieżką powiększającą względem <math>M'</math>, i <math>M'</math> nie jest maksymalne. Zatem <math>P</math> przecina się z <math>Z</math>. Ponieważ <math>Z</math> ma jeden wierzchołek wolny to, co najmniej jeden z końców <math>P</math> nie leży na <math>Z</math>, oznaczmy ten wierzchołek przez <math>x</math>. Poczynając od <math>x</math> niech <math>z</math> będzie pierwszym punktem na ścieżce <math>Z</math> leżącym na <math>P</math>. Wtedy <math>P[x,z]</math> jest ścieżką powiększającą względem <math>M'</math> w <math>G'</math>, ponieważ <math>Z</math> po ściągnięciu do <math>z</math> jest wolny.
Udowodnijmy najpierw, że jeżeli <math>M'</math> jest skojarzeniem maksymalnym, to także <math>M</math> jest maksymalne. Załóżmy przeciwnie, że <math>M</math> nie jest maksymalnym skojarzeniem w G. Wtedy istnieje ścieżka powiększająca <math>P</math> względem <math>M</math>. Jeżeli <math>P</math> jest rozłączna z <math>Z</math>, to <math>P</math> także jest ścieżką powiększającą względem <math>M'</math> i <math>M'</math> nie jest maksymalne. Zatem <math>P</math> przecina się z <math>Z</math>. Ponieważ <math>Z</math> ma jeden wierzchołek wolny, to co najmniej jeden z końców <math>P</math> nie leży na <math>Z</math>. Oznaczmy ten wierzchołek przez <math>x</math>. Poczynając od <math>x</math>, niech <math>z</math> będzie pierwszym punktem na ścieżce <math>Z</math> leżącym na <math>P</math>. Wtedy <math>P[x,z]</math> jest ścieżką powiększającą względem <math>M'</math> w <math>G'</math>, ponieważ <math>Z</math> po ściągnięciu do <math>z</math> jest wolny.


Pokażemy teraz, że w lemacie zachodzi także wynikanie w drugim kierunku. Niech <math>M'</math> nie będzie maksymalnym skojarzeniem w <math>G'</math> oraz niech <math>N'</math> będzie liczniejszym skojarzeniem w <math>G'</math>. Rozwińmy cykl <math>Z</math> aby odtworzyć <math>G</math>. Wtedy <math>N'</math> będzie skojarzeniem w <math>G</math> kojarzącym co najwyżej jeden wierzchołek z <math>Z</math>. Możemy wtedy <math>N'</math> powiększyć o <math>k</math> krawędzi z <math>Z</math> otrzymując skojarzenie <math>N</math>, o rozmiarze:
Pokażemy teraz, że w lemacie zachodzi także wynikanie w drugim kierunku. Niech <math>M'</math> nie będzie maksymalnym skojarzeniem w <math>G'</math> oraz niech <math>N'</math> będzie liczniejszym skojarzeniem w <math>G'</math>. Rozwińmy cykl <math>Z</math>, aby odtworzyć <math>G</math>. Wtedy <math>N'</math> będzie skojarzeniem w <math>G</math>, kojarzącym co najwyżej jeden wierzchołek z <math>Z</math>. Możemy wtedy <math>N'</math> powiększyć o <math>k</math> krawędzi z <math>Z</math>, otrzymując skojarzenie <math>N</math> o rozmiarze:


{{wzor2|1=
{{wzor2|1=
<math>|N| = |N'| + k > |M'| + k = |M|</math>.
<math>|N| = |N'| + k > |M'| + k = |M|</math>.
}}
}}
 
Tak więc <math>M</math> nie jest maksymalnym skojarzeniem w <math>G</math>, co kończy dowód lematu.
Czyli <math>M</math> nie jest maksymalnym skojarzeniem w <math>G</math>, co kończy dowód lematu.
}}
}}


Lemat ten zobrazowany jest na poniższej animacji.
Lemat ten zobrazowany jest na poniższej animacji.
<flash>file=Zasd_ilustr_m.swf |width=600|height=500</flash>
[[File:Zasd_ilustr_m.svg|600x500px|thumb|center]]
 
Zauważmy, że jeżeli znajdziemy większe skojarzenie od <math>M'</math> w <math>G'</math>, to nie tylko wiemy, że <math>M</math> nie jest maksymalnym skojarzeniem, ale także umiemy skonstruować to większe skojarzenie. Zanim wykorzystamy obserwację w konstrukcji algorytmu Edmondsa, wprowadźmy pewne oznaczenia.
Zauważmy, że jeżeli znajdziemy większe skojarzenie od <math>M'</math> w <math>G'</math>, to nie tylko wiemy, że <math>M</math> nie jest maksymalnym skojarzeniem, ale także umiemy skonstruować to większe skojarzenie. Zanim wykorzystamy obserwację w konstrukcji algorytmu Edmondsa wprowadźmy pewne oznaczenia.


== Algorytm Edmondsa ==
== Algorytm Edmondsa ==
Linia 59: Linia 57:
Niech <math>M</math> będzie pewnym skojarzeniem oraz niech S oznacza zbiór wierzchołków wolnych dla <math>M</math>. {{kotwica|las_alternujący|'''Lasem <math>M</math>-alternującym'''}} nazwiemy las <math>L</math> taki, że:
Niech <math>M</math> będzie pewnym skojarzeniem oraz niech S oznacza zbiór wierzchołków wolnych dla <math>M</math>. {{kotwica|las_alternujący|'''Lasem <math>M</math>-alternującym'''}} nazwiemy las <math>L</math> taki, że:
* korzeniem każdego drzewa w <math>L</math> jest wierzchołek <math>S</math> i drzewo to nie zawiera innych wierzchołków z <math>S</math>,
* korzeniem każdego drzewa w <math>L</math> jest wierzchołek <math>S</math> i drzewo to nie zawiera innych wierzchołków z <math>S</math>,
* każdy wierzchołek <math>S</math> należy do jednej składowej <math>F</math>,
* każdy wierzchołek <math>S</math> należy do jednej składowej <math>L</math>,
* każda krawędź w odległości nieparzystej od kożenia należy do <math>M</math>.
* każda krawędź w odległości nieparzystej od korzenia należy do <math>M</math>.


Zauważmy, że każdy punkt w lesie <math>L</math> w odległości parzystej od <math>S</math> ma stopień <math>2</math>, takie punkty nazywać będziemy '''wewnętrznymi'''. Pozostałe punkty w <math>L</math> nazywać będziemy '''zewnętrznymi'''. Na przykład las składający się tylko z punktów <math>S</math> jest <math>M</math>-alternujący.
Zauważmy, że każdy punkt w lesie <math>L</math> w odległości parzystej od <math>S</math> ma stopień <math>2</math>. Takie punkty nazywać będziemy '''wewnętrznymi'''. Pozostałe punkty w <math>L</math> nazywać będziemy '''zewnętrznymi'''. Dla przykładu, las składający się tylko z punktów <math>S</math> jest <math>M</math>-alternujący.


{{algorytm|Edmondsa|EDMONDS|3=
{{algorytm|Edmondsa|EDMONDS|3=
   EDMONDS(G = (V,E))
   EDMONDS<math>(G = (V,E))</math>
   1  <math>M = \emptyset</math>
   1  <math>M = \emptyset</math>
   2  las <math>L</math> to zbiór wierzchołków wolnych
   2  las <math>L</math> to zbiór wierzchołków wolnych
Linia 101: Linia 99:


Działanie tego algorytmu zobrazowane jest na poniższej animacji.
Działanie tego algorytmu zobrazowane jest na poniższej animacji.
<flash>file=Zasd_Ilustr_n.swf |width=600|height=500</flash>
[[File:Zasd_ilustr_n.svg|600x500px|thumb|center]]
 


{{twierdzenie|4|edmonds|3=
{{twierdzenie|4|edmonds|3=
Linia 109: Linia 106:


{{dowod|||3=
{{dowod|||3=
Algorytm Edmondsa kończy działanie gdy każdy wierzchołek zewnętrzny w <math>L</math> ma jako sąsiadów wierzchołki wewnętrzne. Oznaczmy przez <math>W</math> zbiór wierzchołków wewnętrznych w <math>L</math> a przez <math>Z</math> zbiór wierzchołków zewnętrznych. Mamy wtedy <math>|Z|-|W| = |V| - 2|M|</math>, ponieważ w każdym drzewie jest jeden wierzchołek zewnętrzny więcej i jest to wierzchołek wolny. Jeżeli usuniemy wierzchołki <math>W</math> z <math>G</math>, to otrzymamy graf składający się z izolowanych wierzchołków zewnętrznych. Dlatego <math>c_n(G-W) = |Z|</math> i
Algorytm Edmondsa kończy działanie, gdy każdy wierzchołek zewnętrzny w <math>L</math> ma jako sąsiadów wierzchołki wewnętrzne. Oznaczmy przez <math>W</math> zbiór wierzchołków wewnętrznych w <math>L</math>, a przez <math>Z</math> zbiór wierzchołków zewnętrznych. Mamy wtedy <math>|Z|-|W| = |V| - 2|M|</math>, ponieważ w każdym drzewie jest jeden wierzchołek zewnętrzny więcej i jest to wierzchołek wolny. Jeżeli usuniemy wierzchołki <math>W</math> z <math>G</math>, otrzymamy graf składający się z izolowanych wierzchołków zewnętrznych. Dlatego <math>c_n(G-W) = |Z|</math> i


{{wzor2|1=
{{wzor2|1=
<math>
<math>
\frac{1}{2}\left(|V| -(c_n(G-W) - |W|)\right) = \frac{1}{2}\left(|V| - |Z| + |W|)\right) = \frac{1}{2}\left(2|M|\right) = |M|,
\frac{1}{2}\left(|V| -(c_n(G-W) - |W|)\right) = \frac{1}{2}\left(|V| - |Z| + |W|)\right) = \frac{1}{2}\left(2|M|\right) = |M|</math>,
</math>
}}
}}


Linia 122: Linia 118:
=== Szczegóły implementacji ===
=== Szczegóły implementacji ===


Wprost zaimplementowany algorytm Ddmondsa zgodnie z tym schematem działać będzie w czasie <math>O(n^2m)</math>. W celu zagwarantowania czasu działania <math>O(n^3)</math> musimy uzupełnić jeszcze kilka szczegółów implementacyjnych. Po pierwsze nie będziemy usuwać wierzchołków należących do ściąganych cykli, tylko etykietować je jako nieaktywne. Natomiast aby reprezentować wierzchołki otrzymane ze ściągnięcia cykli będziemy dodawać nowe wierzchołki je reprezentujące - zwane pseudowierzchołkami. Dzięki temu łatwiej będzie nam odtwarzać sieć przy rozwijaniu ściągniętych cykli. Krawędzie mające jeden koniec będący wierzchołkiem nieaktywnym nazywać będziemy także nieaktywnymi. Pozostałe krawędzie są aktywne. W trakcie działania algorytmu ignorujemy wierzchołki i krawędzie nieaktywne.
Wprost zaimplementowany algorytm Edmondsa zgodnie z tym schematem działać będzie w czasie <math>O(n^2m)</math>. Aby zagwarantować czas działania <math>O(n^3)</math>, musimy uzupełnić jeszcze kilka szczegółów implementacyjnych. Po pierwsze, nie będziemy usuwać wierzchołków należących do ściąganych cykli, tylko etykietować je jako nieaktywne. Natomiast aby reprezentować wierzchołki otrzymane ze ściągnięcia cykli, będziemy dodawać nowe wierzchołki je reprezentujące - zwane pseudowierzchołkami. Dzięki temu łatwiej będzie nam odtwarzać sieć przy rozwijaniu ściągniętych cykli. Krawędzie mające jeden koniec będący wierzchołkiem nieaktywnym nazywać będziemy także nieaktywnymi. Pozostałe krawędzie są aktywne. W trakcie działania algorytmu ignorujemy wierzchołki i krawędzie nieaktywne.


Trzymanie informacji o krawędziach nieaktywnych w grafie może zwiększyć długość list sąsiedztwa. Po ściągnięciu kielicha wszystkie sąsiednie do niego wierzchołki wierzchołki mają listy sąsiedztwa dłuższe o 1. Jednak jest co najwyżej <math>n/2</math> kontrakcji więc listy te długości co najwyżej <math>\frac{3}{2}n</math>.
Trzymanie informacji o krawędziach nieaktywnych w grafie może zwiększyć długość list sąsiedztwa. Po ściągnięciu cyklu wszystkim sąsiadującym z nim wierzchołkom wydłużają się listy sąsiedztwa o <math>1</math>. Jednak w trakcie działania algorytmu wykonanych będzie co najwyżej <math>n/2</math> kontrakcji, więc listy te będą długości co najwyżej <math>\frac{3}{2}n</math>.


Pokażemy teraz, że między znalezieniem kolejnych ścieżek powiększających upłynie czas <math>O(n^2)</math>. Pomijając czas potrzebny na ściąganie i rozwijanie cykli czas potrzebny na przetworzenie każdego wierzchołka wynosi <math>O(n)</math>. Każdy wierzchołek przetworzony będzie tylko raz, w momencie dodania go do lasu <math>L</math>, dlatego całkowity czas to <math>O(n^2)</math>. Pokażemy teraz, że na ściągnięcie wszystkich cykli i ich późniejsze rozwinięcie potrzeba także czasu <math>O(n^2)</math>.
Pokażemy teraz, że między znalezieniem kolejnych ścieżek powiększających upłynie czas <math>O(n^2)</math>. Pomijając czas potrzebny na ściąganie i rozwijanie cykli, czas potrzebny na przetworzenie każdego wierzchołka wynosi <math>O(n)</math>. Każdy wierzchołek przetworzony będzie tylko raz, w momencie dodania go do lasu <math>L</math>, dlatego całkowity czas to <math>O(n^2)</math>. Pokażemy teraz, że na ściągnięcie wszystkich cykli i ich późniejsze rozwinięcie potrzeba także czasu <math>O(n^2)</math>.


Zajmijmy się teraz ściąganiem cykli. Niech <math>i_1 - i_2 -\ldots - i_k - i_1</math> to cykl <math>C</math>. Problemem jest tutaj stworzenie listy sąsiadów <math>\Gamma(b) = \Gamma(i_1) \cup \Gamma(i_2) \cup \ldots \Gamma(i_k)</math>, dla pseudowierzchołka <math>b</math> reprezentującego <math>B</math> po ściągnięciu. W tym celu:
Zajmijmy się teraz ściąganiem cykli. Niech <math>i_1 - i_2 -\ldots - i_k - i_1</math> to cykl <math>C</math>. Problemem jest tutaj stworzenie listy sąsiadów <math>\Gamma(b) = \Gamma(i_1) \cup \Gamma(i_2) \cup \ldots \Gamma(i_k)</math> dla pseudowierzchołka <math>b</math> reprezentującego <math>B</math> po ściągnięciu. W tym celu:
* przeglądamy wierzchołki <math>i_j</math> należące do kielicha i zaznaczmy wierzchołki z <math>\Gamma(i_j)</math>,
* przeglądamy wierzchołki <math>i_j</math> należące do cyklu i zaznaczmy wierzchołki z <math>\Gamma(i_j)</math>,
* przeglądamy teraz wierzchołki grafu i tworzymy listę wierzchołków zaznaczonych --- to jest właśnie <math>\Gamma(b)</math>,
* przeglądamy teraz wierzchołki grafu i tworzymy listę wierzchołków zaznaczonych - to jest właśnie <math>\Gamma(b)</math>,
* dodajemy <math>b</math> jako sąsiada wierzchołków <math>\Gamma(b)</math>.
* dodajemy <math>b</math> jako sąsiada wierzchołków <math>\Gamma(b)</math>.


Zauważmy, że każdy wierzchołek tylko raz może należeć do kielicha. Przejrzenie list <math>\Gamma(i_j)</math> i markowanie wierzchołków zajmie więc w sumie czas <math>O(n^2)</math>. Pozostałe czynności w zajmują zawsze czas <math>O(n)</math> co w sumie daje czas <math>O(n^2)</math>.
Zauważmy, że każdy wierzchołek tylko raz może należeć do ściąganego cyklu. Przejrzenie list <math>\Gamma(i_j)</math> i markowanie wierzchołków zajmie więc w sumie czas <math>O(n^2)</math>. Pozostałe czynności w zajmują zawsze czas <math>O(n)</math>, co w sumie daje czas <math>O(n^2)</math>.


Przejdźmy teraz do problemu rozwinięcia cykli. Samo rozwinięcie cykli może być zrealizowane w czasie <math>O(n^2)</math>, poprzez przejrzenie wszystkich wierzchołków oraz krawędzi w grafie w trakcie którego usuwamy wszystkich pseudowierzchołki i markujemy nieaktywne elementy grafu jako aktywne. Robiąc to musimy jednak pamiętać także o rozwijaniu ścieżki <math>P = P_1 + P_2 + x_1x_2</math>. Najpierw przechodząc ścieżkę markujemy wszystkie wierzchołki <math>v</math> do niej należące i zapisujemy dla niech w zmiennej <math>p(v)</math> ich poprzedników na ścieżce oraz w zmiennej <math>n(v)</math> ich następników. Jeżeli teraz rozwijamy pseudowierzchołek <math>v</math>, który leży na ścieżce, to:
Przejdźmy teraz do problemu rozwinięcia cykli. Samo rozwinięcie cykli może być zrealizowane w czasie <math>O(n^2)</math> poprzez przejrzenie wszystkich wierzchołków oraz krawędzi w grafie, w trakcie którego usuwamy wszystkie pseudowierzchołki i markujemy nieaktywne elementy grafu jako aktywne. Robiąc to, musimy jednak pamiętać także o rozwijaniu ścieżki <math>P = P_1 + P_2 + x_1x_2</math>. Najpierw, przechodząc ścieżkę markujemy wszystkie wierzchołki <math>v</math> do niej należące i zapisujemy dla nich w zmiennej <math>p(v)</math> ich poprzedników na ścieżce oraz w zmiennej <math>n(v)</math> ich następników. Jeżeli teraz rozwijamy pseudowierzchołek <math>v</math>, który leży na ścieżce, to:
* markujemy najpierw wierzchołki należące do ściągniętego cyklu reprezentowanego przez pseudowierzchołek <math>v</math>,
* markujemy najpierw wierzchołki należące do ściągniętego cyklu reprezentowanego przez pseudowierzchołek <math>v</math>,
* przeszukujemy listę sąsiadów <math>p(v)</math> w celu znalezienia zamarkowanego wierzchołka <math>k_p</math>.
* przeszukujemy listę sąsiadów <math>p(v)</math> w celu znalezienia zamarkowanego wierzchołka <math>k_p</math>.
Linia 141: Linia 137:
* przechodzimy ściągnięty cykl w kierunku zadanym przez parzystość ścieżki, od wierzchołka <math>k_p</math> do wierzchołka <math>k_q</math>.
* przechodzimy ściągnięty cykl w kierunku zadanym przez parzystość ścieżki, od wierzchołka <math>k_p</math> do wierzchołka <math>k_q</math>.


W ten sposób dla każdego rozwijanego kielicha musimy wykonać <math>O(n)</math> dodatkowych operacji, co przy rozwijaniu <math>n-1</math> kielichów daje złożoność <math>O(n^3)</math>.
W ten sposób dla każdego rozwijanego kielicha musimy wykonać <math>O(n)</math> dodatkowych operacji, co przy rozwijaniu <math>n-1</math> kielichów daje złożoność <math>O(n^2)</math>.

Aktualna wersja na dzień 21:50, 11 wrz 2023

Abstrakt

W wykładzie tym skupimy się na problemie znajdowania maksymalnych skojarzeń w dowolnych grafach. Zaczniemy od postawienia twierdzenia Berge'a i udowodnienia jego części. Następnie przedstawimy i udowodnimy lemat o ściąganiu cykli. Wykorzystamy ten lemat w konstrukcji algorytmu Edmondsa, znajdującego maksymalne skojarzenia w czasie O(|V|3). Algorytm ten będzie jednocześnie konstruktywnym dowodem twierdzenia Berga.

Skojarzenie w grafach dowolnych

Na poprzednim wykładzie, aby pokazać poprawność algorytmu znajdowania doskonałych skojarzeń, skorzystaliśmy z twierdzenia Berge'a o ścieżkach powiększających, które mówiło, że skojarzenie jest maksymalne, gdy nie istnieje względem niego ścieżka powiększająca. Tutaj skorzystamy z komplementarnego podejścia, a mianowicie wykorzystamy poniższy lemat. Jednak do jego sformułowania musimy wprowadzić jedno oznaczenie. Niech cn(G) oznacza liczbę spójnych składowych grafu G o nieparzystej liczbie wierzchołków.

Lemat 1

Dla dowolnego skojarzenia M w grafie G=(V,E) i dowolnego podzbioru wierzchołków XV zachodzi

|M|12(|V|(cn(GX)|X|))      (1)

Dowód

Zauważmy, że jeżeli nieparzystej składowej z grafu GX nie skojarzymy z wierzchołkiem z X, to pozostanie w niej co najmniej jeden wierzchołek wolny. Ponieważ z cn(GX) nieparzystych składowych możemy skojarzyć w ten sposób co najwyżej |X|, to dla dowolnego skojarzenia M w grafie pozostanie co najmniej cn(GX)|X| wierzchołków wolnych. Tak więc skojarzonych wierzchołków będzie co najwyżej |V|(cn(GX)|X|), a co za tym idzie, rozmiar M jest ograniczony tak jak we wzorze 1.

Lemat ten mówi, że aby udowodnienić, że skojarzenie M jest maksymalne, musimy pokazać zbiór XV, dla którego we wzorze 1 będzie zachodziła równość. Niestety, lemat ten nie mówi, że taki zbiór musi istnieć. Jednak algorytm Edmondsa, który za chwilę przedstawimy, pozwoli na konstrukcję takiego zbioru, a tym samym pozwoli nam na udowodnienie następującej silniejszej wersji Lematu 1.

Twierdzenie 2 [Twierdzenie Berge'a]

Niech M będzie maksymalnym skojarzeniem w grafie G=(V,E), wtedy

|M|=minXV12(|V|(c0(GX)|X|))      (2)

Lemat o ściąganiu cykli

Głównym problemem w konstrukcji algorytmu, znajdującego maksymalne skojarzenie w grafach dowolnych, jest problem znalezienia ścieżki powiększającej. Niestety, konstrukcja grafu GM użyta przez nas na poprzednim wykładzie tutaj nie zadziała, ponieważ teraz mogą istnieć naprzemienne ścieżki zaczynające się w wierzchołku wolnym i kończące się krawędzią skojarzoną i nie skojarzoną w wybranym wierzchołku. Nie możemy więc po prostu pamiętać, czy wierzchołek został juz odwiedzony i użyć dzięki temu prostego przeszukiwania grafu. Aby poradzić sobie z takimi trudnymi przypadkami, użyjemy następującego lematu.

Lemat 3 [O ściąganiu cykli]

Dla grafu G niech:
  • M będzie skojarzeniem w G,
  • Z będzie cyklem długości 2k+1 zawierającym k krawędzi z M i rozłącznym z resztą M.
Skonstruujmy nowy graf G z G poprzez ściągnięcie Z do jednego wierzchołka. Skojarzenie M=ME(Z) jest maksymalne w G wtedy i tylko wtedy, gdy skojarzenie M jest maksymalne w G.

Dowód

Udowodnijmy najpierw, że jeżeli M jest skojarzeniem maksymalnym, to także M jest maksymalne. Załóżmy przeciwnie, że M nie jest maksymalnym skojarzeniem w G. Wtedy istnieje ścieżka powiększająca P względem M. Jeżeli P jest rozłączna z Z, to P także jest ścieżką powiększającą względem M i M nie jest maksymalne. Zatem P przecina się z Z. Ponieważ Z ma jeden wierzchołek wolny, to co najmniej jeden z końców P nie leży na Z. Oznaczmy ten wierzchołek przez x. Poczynając od x, niech z będzie pierwszym punktem na ścieżce Z leżącym na P. Wtedy P[x,z] jest ścieżką powiększającą względem M w G, ponieważ Z po ściągnięciu do z jest wolny.

Pokażemy teraz, że w lemacie zachodzi także wynikanie w drugim kierunku. Niech M nie będzie maksymalnym skojarzeniem w G oraz niech N będzie liczniejszym skojarzeniem w G. Rozwińmy cykl Z, aby odtworzyć G. Wtedy N będzie skojarzeniem w G, kojarzącym co najwyżej jeden wierzchołek z Z. Możemy wtedy N powiększyć o k krawędzi z Z, otrzymując skojarzenie N o rozmiarze:

|N|=|N|+k>|M|+k=|M|.
Tak więc M nie jest maksymalnym skojarzeniem w G, co kończy dowód lematu.

Lemat ten zobrazowany jest na poniższej animacji.

Plik:Zasd ilustr m.svg

Zauważmy, że jeżeli znajdziemy większe skojarzenie od M w G, to nie tylko wiemy, że M nie jest maksymalnym skojarzeniem, ale także umiemy skonstruować to większe skojarzenie. Zanim wykorzystamy tę obserwację w konstrukcji algorytmu Edmondsa, wprowadźmy pewne oznaczenia.

Algorytm Edmondsa

Niech M będzie pewnym skojarzeniem oraz niech S oznacza zbiór wierzchołków wolnych dla M. Lasem M-alternującym nazwiemy las L taki, że:

  • korzeniem każdego drzewa w L jest wierzchołek S i drzewo to nie zawiera innych wierzchołków z S,
  • każdy wierzchołek S należy do jednej składowej L,
  • każda krawędź w odległości nieparzystej od korzenia należy do M.

Zauważmy, że każdy punkt w lesie L w odległości parzystej od S ma stopień 2. Takie punkty nazywać będziemy wewnętrznymi. Pozostałe punkty w L nazywać będziemy zewnętrznymi. Dla przykładu, las składający się tylko z punktów S jest M-alternujący.

Algorytm Edmondsa


 EDMONDS(G=(V,E))
 1  M=
 2  las L to zbiór wierzchołków wolnych
 3  repeat
 4    if istnieje zewnętrzny wierzchołek xL sąsiedni z wierzchołkiem yL then
 5    begin
 6      znajdź wierzchołek z taki, że yzM
 7      L=L+xy+yz
 8    end
 9    else if x1,x2L to wierzchołki zewnętrzne połączone krawędzią then
 10   begin
 11     if x1,x2 należą do różnych składowych L then
 12     begin
 13       niech Pi to ścieżka z xi do korzenia jego składowej
 14       rozwiń wszystkie ściągnięte cykle w grafie G
 15       M=M(P1+P2+x1x2)
 16       las L to zbiór wierzchołków wolnych
 17     end
 18     else
 19     begin
 20       niech C będzie cyklem utworzonym przez krawędź x1x2 oraz ścieżkę xy w L,
 21       niech P będzie ścieżką w L łączącą C z korzeniem drzewa
 22       M=MP
 23       utwórz graf G poprzez ściągnięcie C
 24       G=G
 25     end
 26   end
 27   else
 28   begin
 29     rozwiń wszystkie ściągnięte cykle w grafie G
 30     return M
 31   end
 32 until FALSE

Działanie tego algorytmu zobrazowane jest na poniższej animacji.

Plik:Zasd ilustr n.svg

Twierdzenie 4

Algorytm Edmondsa znajduje maksymalne skojarzenie M w grafie G.

Dowód

Algorytm Edmondsa kończy działanie, gdy każdy wierzchołek zewnętrzny w L ma jako sąsiadów wierzchołki wewnętrzne. Oznaczmy przez W zbiór wierzchołków wewnętrznych w L, a przez Z zbiór wierzchołków zewnętrznych. Mamy wtedy |Z||W|=|V|2|M|, ponieważ w każdym drzewie jest jeden wierzchołek zewnętrzny więcej i jest to wierzchołek wolny. Jeżeli usuniemy wierzchołki W z G, otrzymamy graf składający się z izolowanych wierzchołków zewnętrznych. Dlatego cn(GW)=|Z| i
12(|V|(cn(GW)|W|))=12(|V||Z|+|W|))=12(2|M|)=|M|,
czyli nierówność w lemacie 1 zachodzi z równością. Skojarzenie M jest więc maksymalne. Zauważmy, że z lematu o ściąganiu cykli wynika, że będzie ono też maksymalne po rozwinięciu wszystkich ściągniętych cykli.

Szczegóły implementacji

Wprost zaimplementowany algorytm Edmondsa zgodnie z tym schematem działać będzie w czasie O(n2m). Aby zagwarantować czas działania O(n3), musimy uzupełnić jeszcze kilka szczegółów implementacyjnych. Po pierwsze, nie będziemy usuwać wierzchołków należących do ściąganych cykli, tylko etykietować je jako nieaktywne. Natomiast aby reprezentować wierzchołki otrzymane ze ściągnięcia cykli, będziemy dodawać nowe wierzchołki je reprezentujące - zwane pseudowierzchołkami. Dzięki temu łatwiej będzie nam odtwarzać sieć przy rozwijaniu ściągniętych cykli. Krawędzie mające jeden koniec będący wierzchołkiem nieaktywnym nazywać będziemy także nieaktywnymi. Pozostałe krawędzie są aktywne. W trakcie działania algorytmu ignorujemy wierzchołki i krawędzie nieaktywne.

Trzymanie informacji o krawędziach nieaktywnych w grafie może zwiększyć długość list sąsiedztwa. Po ściągnięciu cyklu wszystkim sąsiadującym z nim wierzchołkom wydłużają się listy sąsiedztwa o 1. Jednak w trakcie działania algorytmu wykonanych będzie co najwyżej n/2 kontrakcji, więc listy te będą długości co najwyżej 32n.

Pokażemy teraz, że między znalezieniem kolejnych ścieżek powiększających upłynie czas O(n2). Pomijając czas potrzebny na ściąganie i rozwijanie cykli, czas potrzebny na przetworzenie każdego wierzchołka wynosi O(n). Każdy wierzchołek przetworzony będzie tylko raz, w momencie dodania go do lasu L, dlatego całkowity czas to O(n2). Pokażemy teraz, że na ściągnięcie wszystkich cykli i ich późniejsze rozwinięcie potrzeba także czasu O(n2).

Zajmijmy się teraz ściąganiem cykli. Niech i1i2iki1 to cykl C. Problemem jest tutaj stworzenie listy sąsiadów Γ(b)=Γ(i1)Γ(i2)Γ(ik) dla pseudowierzchołka b reprezentującego B po ściągnięciu. W tym celu:

  • przeglądamy wierzchołki ij należące do cyklu i zaznaczmy wierzchołki z Γ(ij),
  • przeglądamy teraz wierzchołki grafu i tworzymy listę wierzchołków zaznaczonych - to jest właśnie Γ(b),
  • dodajemy b jako sąsiada wierzchołków Γ(b).

Zauważmy, że każdy wierzchołek tylko raz może należeć do ściąganego cyklu. Przejrzenie list Γ(ij) i markowanie wierzchołków zajmie więc w sumie czas O(n2). Pozostałe czynności w zajmują zawsze czas O(n), co w sumie daje czas O(n2).

Przejdźmy teraz do problemu rozwinięcia cykli. Samo rozwinięcie cykli może być zrealizowane w czasie O(n2) poprzez przejrzenie wszystkich wierzchołków oraz krawędzi w grafie, w trakcie którego usuwamy wszystkie pseudowierzchołki i markujemy nieaktywne elementy grafu jako aktywne. Robiąc to, musimy jednak pamiętać także o rozwijaniu ścieżki P=P1+P2+x1x2. Najpierw, przechodząc tę ścieżkę markujemy wszystkie wierzchołki v do niej należące i zapisujemy dla nich w zmiennej p(v) ich poprzedników na ścieżce oraz w zmiennej n(v) ich następników. Jeżeli teraz rozwijamy pseudowierzchołek v, który leży na ścieżce, to:

  • markujemy najpierw wierzchołki należące do ściągniętego cyklu reprezentowanego przez pseudowierzchołek v,
  • przeszukujemy listę sąsiadów p(v) w celu znalezienia zamarkowanego wierzchołka kp.
  • przeszukujemy listę sąsiadów q(v) w celu znalezienia zamarkowanego wierzchołka kq.
  • przechodzimy ściągnięty cykl w kierunku zadanym przez parzystość ścieżki, od wierzchołka kp do wierzchołka kq.

W ten sposób dla każdego rozwijanego kielicha musimy wykonać O(n) dodatkowych operacji, co przy rozwijaniu n1 kielichów daje złożoność O(n2).