Zaawansowane algorytmy i struktury danych/Wykład 8
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 , gdzie to liczba wierzchołków w grafie. Algorytm ten będzie jednocześnie końcem dowodu twierdzenia Berga.
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 oznacza liczbę spójnych składowych grafu o nieparzystej liczbie wierzchołków.
Lemat 1
(1)
Dowód

Lemat ten mówi, że w celu udowodnienia, że skojarzenie jest maksymalne musimy pokazać zbiór taki, że 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 chile przedstawimy, pozwoli na konstrukcje takiego zbioru, a tym samym pozwoli nam na udowodnienie następującej silniejszej wersji Lematu 1.
Twierdzenie 2 [Berge'a]
(2)
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 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.
Lemat 3 [O ściąganiu cykli]
- będzie skojarzeniem w ,
- będzie cyklem długości zawierającym krawędzi z i rozłącznym z resztą .
Dowód
Pokażemy teraz, że w lemacie zachodzi także wynikanie w drugim kierunku. Niech nie będzie maksymalnym skojarzeniem w oraz niech będzie liczniejszym skojarzeniem w . Rozwińmy cykl aby odtworzyć . Wtedy będzie skojarzeniem w kojarzącym co najwyżej jeden wierzchołek z . Możemy wtedy powiększyć o krawędzi z otrzymując skojarzenie , o rozmiarze:

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 w , to nie tylko wiemy, że 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 będzie pewnym skojarzeniem oraz niech S oznacza zbiór wierzchołków wolnych dla . Lasem -alternującym nazwiemy las taki, że:
- korzeniem każdego drzewa w jest wierzchołek i drzewo to nie zawiera innych wierzchołków z ,
- każdy wierzchołek należy do jednej składowej ,
- każda krawędź w odległości nieparzystej od kożenia należy do .
Zauważmy, że każdy punkt w lesie w odległości parzystej od ma stopień , takie punkty nazywać będziemy wewnętrznymi. Pozostałe punkty w nazywać będziemy zewnętrznymi. Na przykład las składający się tylko z punktów jest -alternujący.
Algorytm Edmondsa
EDMONDS(G = (V,E)) 1 2 las to zbiór wierzchołków wolnych 3 repeat 4 if istnieje zewnętrzny wierzchołek sąsiedni z wierzchołkiem then 5 begin 6 znajdź wierzchołek taki, że 7 8 end 9 else if to wierzchołki zewnętrzne połączone krawędzią then 10 begin 11 if należą do różnych składowych then 12 begin 13 niech to ścieżka z do korzenia jego składowej 14 rozwiń wszystkie ściągnięte cykle w grafie 15 16 las to zbiór wierzchołków wolnych 17 end 18 else 19 begin 20 niech będzie cyklem utworzonym przez krawędź oraz ścieżkę w , 21 niech będzie ścieżką w łączącą z korzeniem drzewa 22 23 utwórz graf poprzez ściągnięcie 24 25 end 26 end 27 else 28 begin 29 rozwiń wszystkie ściągnięte cykle w grafie 30 return 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
Dowód

Szczegóły implementacji
Wprost zaimplementowany algorytm Ddmondsa zgodnie z tym schematem działać będzie w czasie . W celu zagwarantowania czasu działania 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 kontrakcji więc listy te są długości co najwyżej .
Pokażemy teraz, że między znalezieniem kolejnych ścieżek powiększających upłynie czas . Pomijając czas potrzebny na ściąganie i rozwijanie cykli czas potrzebny na przetworzenie każdego wierzchołka wynosi . Każdy wierzchołek przetworzony będzie tylko raz, w momencie dodania go do lasu , dlatego całkowity czas to . Pokażemy teraz, że na ściągnięcie wszystkich cykli i ich późniejsze rozwinięcie potrzeba także czasu .
Zajmijmy się teraz ściąganiem cykli. Niech to cykl . Problemem jest tutaj stworzenie listy sąsiadów , dla pseudowierzchołka reprezentującego po ściągnięciu. W tym celu:
- przeglądamy wierzchołki należące do kielicha i zaznaczmy wierzchołki z ,
- przeglądamy teraz wierzchołki grafu i tworzymy listę wierzchołków zaznaczonych --- to jest właśnie ,
- dodajemy jako sąsiada wierzchołków .
Zauważmy, że każdy wierzchołek tylko raz może należeć do kielicha. Przejrzenie list i markowanie wierzchołków zajmie więc w sumie czas . Pozostałe czynności w zajmują zawsze czas co w sumie daje czas .
Przejdźmy teraz do problemu rozwinięcia cykli. Samo rozwinięcie cykli może być zrealizowane w czasie , 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 . Najpierw przechodząc tą ścieżkę markujemy wszystkie wierzchołki do niej należące i zapisujemy dla niech w zmiennej ich poprzedników na ścieżce oraz w zmiennej ich następników. Jeżeli teraz rozwijamy pseudowierzchołek , który leży na ścieżce, to:
- markujemy najpierw wierzchołki należące do ściągniętego cyklu reprezentowanego przez pseudowierzchołek ,
- przeszukujemy listę sąsiadów w celu znalezienia zamarkowanego wierzchołka .
- przeszukujemy listę sąsiadów w celu znalezienia zamarkowanego wierzchołka .
- przechodzimy ściągnięty cykl w kierunku zadanym przez parzystość ścieżki, od wierzchołka do wierzchołka .
W ten sposób dla każdego rozwijanego kielicha musimy wykonać dodatkowych operacji, co przy rozwijaniu kielichów daje złożoność .