Minimalne drzewo rozpinaj¡ce
dr Andrzej Mróz (UMK w Toruniu)2013
Projekt wspóªnansowany ze ±rodków Unii Europejskiej w ramach Europejskiego Funduszu Spoªecznego Projekt pn. Wzmocnienie potencjaªu dydaktycznego UMK w Toruniu w dziedzinach
matematyczno-przyrodniczych
Spis tre±ci
1 Wst¦p 3
1.1 Problem . . . 3
1.2 Drzewo rozpinaj¡ce . . . 3
1.3 Drzewo rozpinaj¡ce przykªad . . . 3
1.4 Minimalne drzewo rozpinaj¡ce . . . 4
1.5 Minimalne drzewo rozpinaj¡ce przykªad . . . 4
1.6 Cel - poszukiwanie MST . . . 5
2 Idee 5 2.1 Strategia . . . 5
2.2 Problem . . . 6
2.3 Idea algorytmu Kruskala . . . 6
2.4 Idea algorytmu Prima . . . 7
3 Zbiory rozª¡czne 7 3.1 Struktury danych dla zbiorów rozª¡cznych . . . 7
3.2 Proste zastosowanie . . . 8
3.3 Heurystyka . . . 8
3.4 Implementacja listy . . . 9
3.5 Implementacja drzewa z korzeniem . . . 9
4 Kruskal 11 4.1 Poprawno±¢ . . . 11
4.2 Przekroje . . . 12
4.3 Algorytm . . . 13
4.4 Przebieg algorytmu Kruskala . . . 13
5 Prim 14 5.1 Poprawno±¢ . . . 14
5.2 Implementacja . . . 15
5.3 Algorytm . . . 15
1 Wst¦p
1.1 Problem
Ustalmy spójny niezorientowany graf G = (V, E) z funkcj¡ wagi w : E → R+.
Rozwa»my nast¦puj¡c¡ interpretacj¦ grafu G: • wierzchoªki V = {1, 2, . . . , n} = miasta,
• kraw¦dzie = potencjalne bezpo±rednie drogowe poª¡czenia pomi¦dzy miastami, • waga w(i, j) kraw¦dzi {i, j} ∈ E = koszt budowy poª¡czenia pomi¦dzy miastami i i j. Zagadnienie optymalizacyjne. Zbudowa¢ tylko te drogi spo±ród opisanych przez graf G (czyli wybra¢ podgraf G0 grafu G) tak, by:
1. pomi¦dzy ka»d¡ par¡ miast (wierzchoªków) istniaªo drogowe poª¡czenie (niekoniecznie bezpo±rednie),
2. koszt budowy tej sieci dróg byª najni»szy spo±ród wszystkich rozwi¡za« speªniaj¡cych punkt 1.
atwo zauwa»y¢, »e je»eli podgraf G0 speªnia te wªasno±ci, to
1. zawiera wszystkie wierzchoªki grafu G, 2. jest spójny,
3. nie zawiera cykli.
W szczególno±ci 2 i 3 oznaczaj¡, »e G0 powinien by¢ drzewem. Tzw. minimalnym drzewem
rozpinaj¡cym, które za chwil¦ zdeniujemy w sposób bardziej formalny.
Problem ten pojawia si¦ w wielu innych kontekstach informatycznych, cz¦sto znalezienie minimalnego drzewa rozpinaj¡cego jest pierwszym krokiem w rozwi¡zaniach innych problemów. Czasem stosuje si¦ te» nazw¦ minimalne drzewo spinaj¡ce.
1.2 Drzewo rozpinaj¡ce
Niech G = (V, E) b¦dzie spójnym grafem niezorientowanym.
Denicja. Drzewo rozpinaj¡ce (ang. spanning tree) grafu G = drzewo T = (V, E0)takie, »e
E0 ⊆ E.
Tzn. T jest drzewem zawieraj¡cym wszystkie wierzchoªki G, za± jego zbiór kraw¦dzi jest podzbiorem zbioru kraw¦dzi G.
• Drzewo rozpinaj¡ce powstaje z grafu G poprzez usuni¦cie kraw¦dzi nale»¡cych do cykli. • Ka»de drzewo rozpinaj¡ce grafu G ma |V | − 1 kraw¦dzi.
1.3 Drzewo rozpinaj¡ce przykªad
Dla grafu G: @ @ @ @ v f vf vf v f vf vf
Drzewem rozpinaj¡cym jest podgraf T :
@ @ @ @ v f vf vf v f vf vf
Ale te» podgraf T2:
v f vf vf v f vf vf Oraz podgraf T3: v f vf vf v f vf vf
1.4 Minimalne drzewo rozpinaj¡ce
Niech G = (V, E) b¦dzie spójnym grafem niezorientowanym z wag¡ w : E → R+.
Dla dowolnego drzewa rozpinaj¡cego T = (V, E0) grafu G deniujemy jego wag¦
w(T ) = X
(u,v)∈E0
w(u, v).
Denicja. Minimalne drzewo rozpinaj¡ce (ang. minimal spanning tree MST) grafu G = drzewo rozpinaj¡ce T o minimalnej wadze w(T ) (spo±ród wszystkich drzew rozpinaj¡cych grafu G).
1.5 Minimalne drzewo rozpinaj¡ce przykªad
Dla grafu z wagami:
@ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9
przykªadowe wagi drzew rozpinaj¡cych:
T : w(T ) = 35 @ @ @ @ 13 10 1 2 9 v f vf vf v f vf vf
T2: 15 w(T2) = 48 2 13 10 8 v f vf vf v f vf vf T3: w(T3) = 33 2 13 8 1 9 v f vf vf v f vf vf
Nietrudno sprawdzi¢, »e dla powy»szego grafu G minimalnym drzewem rozpinaj¡cym jest T3.
Ale zauwa»my, »e T3 nie jest jedynym MST. Inne drzewo rozpinaj¡ce o tej samej wadze co T3:
T4: w(T4) = 33 @ @ @ @ 13 8 1 2 9 v f vf vf v f vf vf 1.6 Cel - poszukiwanie MST
Rozwi¡zanie naiwne: Wygenerowa¢ wszystkie drzewa rozpinaj¡ce i wybra¢ te o najmniejszej wadze.
Oczywista wada: Drzew rozpinaj¡cych jest na ogóª bardzo du»o. Ponadto, wcale nie jest to takie proste pod wzgl¦dem implementacyjnym. Cel: Opracowa¢ efektywn¡ metod¦ znajdowania (jakiegokolwiek) MST.
2 Idee
2.1 Strategia
Ogólna strategia zachªanna rozrastanie si¦ podgrafu T o zbiorze kraw¦dzi A, który na ko«cu b¦dzie MST.
Dane: Spójny graf niezorientowany G = (V, E) z funkcj¡ wagow¡ w : E → R+.
Cel: Znalezienie MST dla G.
• Podgraf T rozrasta si¦ w wyniku dodawania kolejnych kraw¦dzi.
• W czasie algorytmu trzymamy zbiór A, który zawsze jest podzbiorem zbioru kraw¦dzi pewnego MST.
• W ka»dym kroku wyznaczamy kraw¦d¹, któr¡ mo»na doda¢ do A bez straty jego wªas-no±ci (kraw¦d¹ bezpieczn¡ dla A).
B¦dziemy zatem realizowa¢ strategi¦ opisan¡ przez bardzo ogólny pseudokod: GenericMST(G, w)
1 begin
2 A := ∅;
3 while A nie tworzy drzewa rozpinaj¡cegodo
4 begin
5 znajd¹ kraw¦d¹ {u, v} ∈ E\A bezpieczn¡ dla A; 6 A := A ∪ { {u, v} }
7 end
8 end;
Poprawno±¢ ogólnie:
• Niezmiennik A jest podzbiorem zbioru kraw¦dzi pewnego MST jest zachowany w ka»dym kroku.
• Kraw¦d¹ bezpieczna w ka»dym kroku istnieje gwarantuje to niezmiennik.
2.2 Problem
Gªówny problem. Jak rozpoznawa¢ bezpieczn¡ kraw¦d¹?
Omówimy dwa ró»ne rozwi¡zania tego problemu, tj. dwie ró»ne realizacje ogólnej strategii GenericMST:
• Algorytm Kruskala. • Algorytm Prima.
2.3 Idea algorytmu Kruskala
Nieformalny opis
• W ka»dym kroku rozrastaj¡cy si¦ podgraf T = (V, A) grafu G jest lasem (tj. jego skªadowe s¡ drzewami).
• Na pocz¡tku A = ∅, tj. skªadowe T to jednowierzchoªkowe drzewa. • Dodaj¡c bezpieczn¡ kraw¦d¹ do A scalamy dwie skªadowe T w jedn¡. • Na ko«cu T scali si¦ w jedno drzewo.
• W poszukiwaniu kraw¦dzi bezpiecznych w kolejnych krokach przetwarzamy kraw¦dzie w kolejno±ci ich rosn¡cych (niemalej¡cych) wag.
• Kraw¦d¹ e jest bezpieczna, gdy dodanie jej do A nie spowoduje pojawienia si¦ cyklu (jest to równowa»ne z tym, »e e ª¡czy dwie ró»ne dotychczasowe skªadowe w T ). Nale»y zatem umie¢ rozpoznawa¢ ró»ne skªadowe w grae T . Do tego wykorzystamy now¡ struktur¦ danych, tzw. struktur¦ zbiorów rozª¡cznych.
2.4 Idea algorytmu Prima
Nieformalny opis
• W odró»nieniu od algorytmu Kruskala, tu T zawsze stanowi jedno drzewo. • Na pocz¡tku T ma 1 wierzchoªek (dowolnie wybrany z G).
• W ka»dym kroku kraw¦d¹ bezpieczna to kraw¦d¹ o najmniejszej wadze spo±ród kraw¦dzi wystaj¡cych z T (tj. ª¡cz¡cych wierzchoªek z T z wierzchoªkiem spoza T ).
Nale»y zatem umie¢ efektywnie wybiera¢ kraw¦dzie bezpieczne j.w. Do tego wykorzystamy odpowiedni¡ kolejk¦ priorytetow¡.
3 Zbiory rozª¡czne
3.1 Struktury danych dla zbiorów rozª¡cznych
W algorytmie Kruskala wykorzystamy nast¦puj¡c¡ dynamiczn¡ struktur¦ danych.
Kontekst: n ró»nych elementów pogrupowanych w pewn¡ liczb¦ zbiorów rozª¡cznych. Cel: zdeniowanie i zarz¡dzanie strukturami danych umo»liwiaj¡cymi operacje m.in.:
• ª¡czenia dwóch zbiorów,
• stwierdzania, do którego zbioru nale»y element x,
• stwierdzania, czy dwa elementy x, y nale»¡ do tego samego zbioru. Zarz¡dzanie rodzin¡ S = {S1, S2, . . . , Sk}rozª¡cznych zbiorów dynamicznych.
Pomysª: ka»dy zbiór Siidentykujemy poprzez jego reprezentanta, czyli wyró»niony element
x ∈ Si.
Warunki nakªadane na reprezentanta:
• na ogóª nie ma znaczenia, który element jest reprezentantem,
• wa»ne jest, by zadaj¡c dwukrotnie pytanie o reprezentanta danego zbioru, otrzyma¢ tak¡ sam¡ odpowied¹, o ile zbiór w tym czasie si¦ nie zmieniaª,
• czasami ustala si¦ na pocz¡tku pewn¡ zasad¦ wyboru reprezentanta (np. element z najmniejszym kluczem...).
Podstawowe operacje:
• MakeSet(x) tworzy nowy jednoelementowy zbiór S = {x} (o reprezentancie x); x nie mo»e by¢ elementem innego zbioru.
• Union(x, y) ª¡czy dwa rozª¡czne zbiory Sx, Sy zawieraj¡ce odpowiednio x i y w nowy
zbiór Sx∪ Sy.
Jego reprezentantem mo»e by¢ dowolny element Sx∪ Sy, na ogóª reprezentant Sx lub
Sy.
• FindSet(x) zwraca wska¹nik do reprezentanta (jedynego) zbioru zawieraj¡cego x. ⇒ stwierdzanie, czy dwa elementy x, y nale»¡ do tego samego zbioru: test FindSet(x) = FindSet(y).
3.2 Proste zastosowanie
Przykªad zastosowania: rozpoznawanie spójnych skªadowych w grae (niezorientowanym) G = (V, E).
ConnectedComponents(G) 1 begin
2 for ka»dy v ∈ Vdo
3 MakeSet(v);
4 for ka»da (u, v) ∈ Edo
5 if FindSet(u) <> FindSet(v)then
6 Union(u, v); 7 end;
Po wykonaniu podziaª wierzchoªków na zbiory rozª¡czne odpowiada podziaªowi na skªadowe spójno±ci. W podobnym kontek±cie wykorzystamy zbiory rozª¡czne w algorytmie Kruskala (który jest de facto pewn¡ modykacj¡ powy»szej procedury).
Teraz, do testowania czy wierzchoªki u i v nale»¡ do tej samej skªadowej mo»emy wykorzysta¢ procedur¦:
SameComponent(u, v) 1 begin
2 if FindSet(u) = FindSet(v)then
3 returntrue 4 else returnfalse 5 end;
• Wiemy: do wyznaczania skªadowych mo»na wykorzysta¢ przegl¡danie grafu.
• Gdy do grafu kraw¦dzie s¡ dodawane w czasie dziaªania algorytmu (czyli trzeba uaktualnia¢ spójne skªadowe), to implementacja przy pomocy zbiorów rozª¡cznych mo»e by¢ efek-tywniejsza.
3.3 Heurystyka
W dalszej cz¦±ci przeprowadzimy prost¡ analiz¦ heurystyczn¡.
Przez heurystyk¦ rozumiemy tu takie projektowanie operacji, by zmniejszy¢ ich koszt zamorty-zowany (niekoniecznie koszt pesymistyczny = zªo»ono±¢ pesymistyczn¡).
Denicja. Koszt zamortyzowany = koszt ±redni operacji P w ci¡gu n wykona« operacji P . Uwaga. Sªowo heurystyka ma w informatyce równie» inne znaczenia.
Przykªad. Wykonujemy kolejno n sortowa« algorytmem sortowania b¡belkowego P na tym samym zbiorze danych X. Wówczas
• tylko za pierwszym razem wykonywane s¡ nietrywialne modykacje na X,
• st¡d tu koszt zamortyzowany jest znacznie ni»szy ni» koszt pesymistyczny algorytmu P . Oczywi±cie koszt zamortyzowany istotnie zale»y od kontekstu wykonywania danej operacji.
3.4 Implementacja listy
Implementacja zbiorów rozª¡cznych w postaci list. • Ka»dy zbiór przechowywany jako (dynamiczna) lista. • Pierwszy skªadnik listy = reprezentant zbioru. • Ka»dy skªadnik listy posiada pola:
element zbioru,
wska¹nik do nast¦pnego skªadnika listy,
wska¹nik (prowadz¡cy wstecz) do reprezentanta.
MakeSet(x) stworzenie nowej listy o jedynym skªadniku x. Zªo»ono±¢: O(1). FindSet(x) zwrócenie wska¹nika od x do reprezentanta zbioru. Zªo»ono±¢: O(1). Union(x, y) doª¡czenie listy Ly z elementem y na koniec listy Lx z elementem x.
• Reprezentantem nowego zbioru jest element b¦d¡cy wcze±niej reprezentantem zbioru zawieraj¡cego x.
• Trzeba uaktualni¢ wska¹nik do reprezentanta we wszystkich skªadnikach znajduj¡cych si¦ pierwotnie na li±cie Ly.
Zªo»ono±¢: O(s), gdzie s = |Ly|(gdy mamy dost¦p do ostatniego elementu Lx).
Usprawnienie: heurystyka ª¡czenia z wywa»aniem. • Zawsze doª¡czamy krótsz¡ list¦ do dªu»szej.
• Trzeba przechowywa¢ (np. w reprezentancie) i uaktualnia¢ rozmiar listy.
Asymptotyczna zªo»ono±¢ pojedynczej operacji Union pozostaje taka sama, lecz koszt zamorty-zowany jest mniejszy.
Pokazuje si¦, »e wykonanie ci¡gu m operacji MakeSet, Union i FindSet, spo±ród których n to MakeSet zajmuje przy wywa»aniu czas O(m + nlog n).
Bez wywa»ania: O(m2).
3.5 Implementacja drzewa z korzeniem
Implementacja w postaci drzew z korzeniem.
• Ka»dy zbiór przechowywany jako drzewo z korzeniem. • Korze« drzewa = reprezentant zbioru.
• Ka»dy wierzchoªek drzewa posiada pola: element zbioru,
wska¹nik do ojca w drzewie (korze« wskazuje na siebie).
Struktur¦ drzewa mo»na tak»e zaimplementowa¢ przy wykorzystaniu tablicy ojców indek-sowanej elementami, które grupujemy w zbiory.
Przykªad. Trzy zbiory rozª¡czne grupuj¡ce 10 elementów, reprezentowane poprzez drzewa: @ @ w g w g w g 1 2 5 @ @ @ @ w g w g w g w g wg wg 3 6 4 7 10 9 w g 8
s¡ jednoznacznie zakodowane przy pomocy tablicy ojców:
i 1 2 3 4 5 6 7 8 9 10 ojciec[i] 2 2 6 6 2 6 4 8 4 4 Operacje:
MakeSet(x) stworzenie nowego drzewa o jedynym wierzchoªku x. Zªo»ono±¢: O(1). FindSet(x) przej±cie po wska¹nikach od x do ojca itp. a» do korzenia.
Zªo»ono±¢: O(h), gdzie h = wysoko±¢ drzewa.
Union(x, y) zmiana wska¹nika w korzeniu drzewa Tx (zawieraj¡cego x) tak aby wskazywaª
na korze« drzewa Ty (zawieraj¡cego y).
Zªo»ono±¢: O(1) (gdy mamy dost¦p do korzeni). Dwie heurystyki:
1. ¡czenie wg wysoko±ci: drzewo o mniejszej wysoko±ci doª¡czamy do drzewa o wi¦kszej wysoko±ci (+ uaktualnienie wysoko±ci).
2. Kompresja drogi: stosowana przy operacji FindSet(x) polega na zmianie wska¹ników we wszystkich wierzchoªkach na drodze od x do korzenia tak, by wskazywaªy na korze«.
Implementacja z uwzgl¦dnieniem heurystyk. Oznaczenia:
• h(x) = wysoko±¢ wierzchoªka x (∈ N),
• ojciec(x) = ojciec wierzchoªka x (wska¹nik lub odwoªanie do tablicy ojców). MakeSet(x)
1 begin
2 ojciec(x) := x; 3 h(x) := 0 4 end;
¡czenie wg wysoko±ci. Wykorzystamy procedur¦ pomocnicz¡: Link(x, y) 1 begin 2 if h(x) > h(y)then 3 ojciec(y) := x 4 else begin 5 ojciec(x) := y; 6 if h(x) = h(y)then 7 h(y) := h(y) + 1 8 end 9 end; Union(x, y) 1 begin 2 Link(FindSet(x), FindSet(y)) 3 end;
FindSet z kompresj¡ drogi: FindSet(x)
1 begin
2 if x <> ojciec(x) then
3 ojciec(x) := FindSet( ojciec(x) ); 4 return ojciec(x)
5 end;
Uwaga. Zauwa»my, »e po FindSet wysoko±¢ drzewa mo»e ulec zmianie (zmniejszeniu). Mimo to, nie uaktualniamy warto±ci h dla »adnego wierzchoªka. Utrzymywanie poprawnych warto±ci wysoko±ci drzew byªoby niepotrzebnie kosztowne. Zatem warto±ci h nale»y tak naprawd¦ inter-pretowa¢ jako górne ograniczenia wysoko±ci drzew.
Zaªó»my, »e wykonujemy ci¡g m operacji MakeSet, Union i FindSet, spo±ród których n to MakeSet.
Twierdzenie (Hopcroft, Ullman). Zªo»ono±¢ wykonania ci¡gu powy»szych operacji z uwzgl¦d-nieniem heurystyk 1 i 2 wynosi O(m log∗n).
log∗ = logarytm iterowany.
log∗ jest funkcj¡ bardzo wolno rosn¡c¡. log∗n ≤ 5dla wszystkich 1 ≤ n ≤ 265536.
Liczba atomów we wszech±wiecie ≈ 1080< 265536.
4 Kruskal
4.1 Poprawno±¢
Zanim przedstawimy konkretny pseudokod, wprowadzimy kilka poj¦¢ i faktów pozwalaj¡cych zrozumie¢, dlaczego idea algorytmu Kruskala przedstawiona wcze±niej zawsze daje poprawne rozwi¡zanie.
Poj¦cia te wyst¦puj¡ te» w innych kontekstach algorytmów grafowych.
Bardziej szczegóªowy dowód poprawno±ci mo»na znale¹¢ np. w ksi¡»ce [1] ze spisu literatury do wykªadu (T. H. Cormen et al.).
4.2 Przekroje
Denicje:
• Ka»dy podzbiór S ⊆ V wyznacza przekrój (S, V \ S) grafu G = (V, E).
• Kraw¦d¹ {u, v} krzy»uje si¦ z przekrojem (S, V \ S), je±li jeden z jej ko«ców nale»y do S, a drugi do V \ S.
• Przekrój (S, V \ S) uwzgl¦dnia zbiór kraw¦dzi A, je±li »adna kraw¦d¹ z A nie krzy»uje si¦ z tym przekrojem.
• Kraw¦d¹ e ∈ E krzy»uj¡ca si¦ z przekrojem jest kraw¦dzi¡ lekk¡, je±li w(e) jest najm-niejsza spo±ród wag wszystkich kraw¦dzi krzy»uj¡cych si¦ z tym przekrojem.
Przytoczymy bez dowodu kluczowy fakt, na którym opiera si¦ uzasadnienie poprawno±ci obu algorytmów. G = (V, E) spójny graf niezorientowany z funkcj¡ wagow¡ w : E → R+
Twierdzenie Niech
• E ⊇ A podzbiór zbioru kraw¦dzi pewnego MST dla G, • (S, V \ S) dowolny przekrój grafu G uwzgl¦dniaj¡cy A, • {u, v} kraw¦d¹ lekka krzy»uj¡ca si¦ z (S, V \ S). Wówczas kraw¦d¹ {u, v} jest bezpieczna dla A.
Przypomnienie idei algorytmu: GenericMST(G, w)
1 begin
2 A := ∅;
3 while A nie tworzy drzewa rozpinaj¡cegodo
4 begin
5 znajd¹ kraw¦d¹ {u, v} ∈ E\A bezpieczn¡ dla A; 6 A := A ∪ { {u, v} }
7 end
8 end;
Rozwa»my graf T = (V, A). W ka»dym kroku jest on acykliczny ⇒ ka»da jego spójna skªadowa jest drzewem.
• na pocz¡tku A = ∅ ⇒ T skªada si¦ z |V | jednowierzchoªkowych drzew,
• poniewa» A ∪ { {u, v} } musi by¢ acykliczny, ka»da bezpieczna kraw¦d¹ {u, v} dla A ª¡czy ró»ne skªadowe z T ,
• w ka»dym kroku kolejne skªadowe T ª¡cz¡ si¦ (liczba drzew maleje), na ko«cu las T zawiera tylko 1 drzewo ⇒ jest MST.
Wniosek Niech
• E ⊇ A podzbiór zbioru kraw¦dzi pewnego MST dla G, • C = spójna skªadowa w lesie T = (V, A),
• {u, v} kraw¦d¹ o najmniejszej wadze spo±ród ª¡cz¡cych C z pewn¡ inn¡ skªadow¡ w T . Wówczas kraw¦d¹ {u, v} jest bezpieczna dla A.
Dowód. Przekrój (C, V \ C) uwzgl¦dnia A.
{u, v} jest kraw¦dzi¡ lekk¡ krzy»uj¡c¡ si¦ z tym przekrojem.
Na mocy twierdzenia {u, v} jest kraw¦dzi¡ bezpieczn¡ dla A.
4.3 Algorytm
Podsumowanie: szczegóªowa wersja algorytmu GenericMST algorytm Kruskala (który jest w pewnym sensie modykacj¡ procedury ConnectedComponents z 3.2).
MST-Kruskal(G, w) 1 begin
2 A := ∅;
3 for ka»dy v ∈ Vdo
4 MakeSet(v);
5 posortuj E niemalej¡co wzgl¦dem wag w;
6 for ka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wag do
7 if FindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 return A 13 end;
Zªo»ono±¢: O(|E| · log|E|) (przy najszybszych implementacjach zbiorów rozª¡cznych i sor-towania, por. Twierdzenie 3.5).
4.4 Przebieg algorytmu Kruskala
@ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9
@ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf 15 2 13 10 8 1 2 9
5 Prim
5.1 Poprawno±¢
Inna realizacja ogólnego algorytmu GenericMST algorytm Prima
• W przeciwie«stwie do algorytmu Kruskala, kraw¦dzie z A tworz¡ zawsze pojedyncze drzewo.
• Pocz¡tkowo drzewo to skªada si¦ z dowolnie wybranego wierzchoªka-korzenia r ∈ V ; nast¦pnie ro±nie do chwili, w której rozpina wszystkie wierzchoªki z V .
• Rozwa»any przekrój: (V (A), V \ V (A)) (V (A) := zbiór ko«ców kraw¦dzi z A).
• W ka»dym kroku dodajemy kraw¦d¹ lekk¡ krzy»uj¡c¡ si¦ z tym przekrojem (tj. kraw¦d¹ o najmniejszej wadze spo±ród tych wystaj¡cych z A).
Przekrój (V (A), V \ V (A)) uwzgl¦dnia A, zatem kraw¦d¹ ta jest bezpieczna dla A (patrz Twierdzenie 4.2).
5.2 Implementacja
Jak wyznacza¢ kraw¦d¹ lekk¡ krzy»uj¡c¡ si¦ z przekrojem (V (A), V \ V (A))?
• Wierzchoªki spoza rozrastaj¡cego si¦ drzewa trzymamy w kolejce priorytetowej Q (por. poprzedni wykªad).
• Dla ka»dego v ∈ V kluczem klucz(v) (tzn. priorytetem wyznaczaj¡cym pozycj¦ w kolejce Q) jest najmniejsza waga spo±ród wag kraw¦dzi ª¡cz¡cych v z wierzchoªkami drzewa. • W zmiennej π[v] pami¦tamy ojca v w obliczanym drzewie.
Podczas wykonywania algorytmu zbiór A jest pami¦tany niejawnie jako A = { {π[v], v} : v ∈ (V \ {r}) \ Q}.
Po zako«czeniu algorytmu Q = ∅, zbiorem kraw¦dzi MST w G jest wi¦c A = { {π[v], v} : v ∈ V \ {r}}.
Przypomnijmy, »e symbolem Adj[u] oznaczamy zbiór s¡siadów wierzchoªka u.
5.3 Algorytm
MST-Prim(G, w, r) 1 begin
2 Q := V;
3 for ka»dy u ∈ Qdoklucz(u) := ∞; 4 klucz(r) := 0;
5 π[r] := ∞; 6 whileQ <> ∅ do
7 begin
8 u := ExtractMin(Q); 9 for ka»dy v ∈ Adj[u]do
10 if (v ∈ Q)and(w(u, v) < klucz(v)) then
11 begin 12 π[v] := u; 13 klucz[v] := w(u, v) 14 end 15 end; 16 return π 17 end;
Zªo»ono±¢: O(|E| · log|V |) (gdy kolejka implementowana na kopcu).
5.4 Przebieg algorytmu Prima
Dowolnie ustalamy korze« r - wierzchoªek startowy.
@ @ @ @ v f vf vf v f vf vf r 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf r 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf r 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf r 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf r 15 2 13 10 8 1 2 9 @ @ @ @ v f vf vf v f vf vf r 15 2 13 10 8 1 2 9