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

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Sank (dyskusja | edycje)
mNie podano opisu zmian
Sank (dyskusja | edycje)
Nie podano opisu zmian
Linia 5: Linia 5:
== 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 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 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 twierdzenie 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 potrzebujemy 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>
Linia 18: Linia 18:
}}
}}


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 konstrukcje takiego zbioru, a tym samym pozwoli nam na udowodnienie następującej silniejszej wersji [[#lemat_1|Lematu 1]].


{{twierdzenie|2 [Twierdzenie 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. W celu poradzenia 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 59: Linia 59:
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 kożenia należy do <math>M</math>.


Linia 122: Linia 122:
=== 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>. 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.


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 wszystkiem sąsiednim 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 scią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 tą ś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 tą ś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:
* 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 141:
* 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>.

Wersja z 09:46, 22 wrz 2006

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 twierdzenie 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 potrzebujemy 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. Czyli 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 konstrukcje 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. W celu poradzenia 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|.
Czyli M nie jest maksymalnym skojarzeniem w G, co kończy dowód lematu.

Lemat ten zobrazowany jest na poniższej animacji. <flash>file=Zasd_Ilustr_m.swf |width=600|height=500</flash>

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 kożenia 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. Na przykład 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. <flash>file=Zasd_Ilustr_n.swf |width=600|height=500</flash>


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, to 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). W celu zagwarantowania czasu 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 wszystkiem sąsiednim 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 scią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 niech 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).