Zaawansowane algorytmy i struktury danych/Wykład 8: Różnice pomiędzy wersjami
Linia 101: | Linia 101: | ||
Działanie tego algorytmu zobrazowane jest na poniższej animacji. | Działanie tego algorytmu zobrazowane jest na poniższej animacji. | ||
<flash>file= | <flash>file=Zasd_ilustr_n.swf |width=600|height=500</flash> | ||
Wersja z 10:58, 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 . 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 oznacza liczbę spójnych składowych grafu o nieparzystej liczbie wierzchołków.
Lemat 1
(1)
Dowód

Lemat ten mówi, że aby udowodnienić, że skojarzenie jest maksymalne musimy pokazać zbiór , 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]
(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 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]
- 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 Edmondsa 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 cyklu wszystkiem sąsiednim z nim wierzchołkom wydłużają się listy sąsiedztwa o . Jednak w trakcie działania algorytmu wykonanych będzie co najwyżej kontrakcji więc listy te będą 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 cyklu 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 sciąganego cyklu. 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 wszystkie 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ść .