Minimalne drzewo rozpinaj¡ce
Autor projektu: dr Andrzej Mróz (UMK)
Projekt pn. Wzmocnienie potencjaªu dydaktycznego UMK w Toruniu w dziedzinach matematyczno-przyrodniczych realizowany w ramach Poddziaªania 4.1.1 Programu Operacyjnego
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.
Problem
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.
Problem
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 informatycz-nych, cz¦sto znalezienie minimalnego drzewa rozpinaj¡cego jest pierwszym krokiem w rozwi¡zaniach innych problemów.
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.
Drzewo rozpinaj¡ce przykªad
Drzewo rozpinaj¡ce nie jest poj¦ciem jednoznacznym. 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
Drzewo rozpinaj¡ce przykªad
Drzewo rozpinaj¡ce nie jest poj¦ciem jednoznacznym. Dla grafu G: @ @ @ @ v f vf vf v f vf vf
Drzewem rozpinaj¡cym jest podgraf T2:
v
f vf vf v
Drzewo rozpinaj¡ce przykªad
Drzewo rozpinaj¡ce nie jest poj¦ciem jednoznacznym. Dla grafu G: @ @ @ @ v f vf vf v f vf vf
Drzewem rozpinaj¡cym jest podgraf T3:
v
f vf vf v
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).
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
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:
T2: 15 w(T2) =48 2 13 10 8 v f vf vf v f vf vf
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:
T3: w(T3) =33 2 13 8 1 9 v f vf vf v f vf vf
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
minimalnym drzewem rozpinaj¡cym jest
T3: w(T3) =33 2 13 8 1 9 v f vf vf v f vf vf
ale nie jest to jedyne MST:
T : w(T ) =33
@
1
v
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.
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ªasno±ci (kraw¦d¹ bezpieczn¡dla A).
Strategia
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.
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.
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¡.
Idea algorytmu Kruskala
Nieformalny opis c.d.
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.
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¡.
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.
Struktury danych dla zbiorów rozª¡cznych
Zarz¡dzanie rodzin¡ S = {S1,S2, . . . ,Sk} rozª¡cznych zbiorów
dynamicznych.
Pomysª: ka»dy zbiór Si identykujemy 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...).
Struktury danych dla zbiorów rozª¡cznych
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).
Proste zastosowanie
Przykªad zastosowania: rozpoznawanie spójnych skªadowych w grae (niezorientowanym) G = (V , E).
ConnectedComponents(G) 1 begin
2 forka»dy v ∈ Vdo
3 MakeSet(v);
4 forka»da (u, v) ∈ Edo
5 ifFindSet(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¡
Proste zastosowanie
SameComponent(u, v) 1 begin
2 ifFindSet(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¢ efektywniejsza.
Heurystyka
W dalszej cz¦±ci przeprowadzimy prost¡ analiz¦ heurystyczn¡. Przezheurystyk¦rozumiemy tu takie projektowanie operacji, by zmniejszy¢ ich kosztzamortyzowany(niekoniecznie koszt pesymistyczny = zªo»ono±¢ pesymistyczn¡).
Denicja
Koszt zamortyzowany = koszt ±redni operacji P w ci¡gu n wykona« operacji P.
Uwaga
Heurystyka
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.
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,
Implementacja listy
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
Implementacja listy
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 zamortyzowany jest mniejszy.
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).
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 indeksowanej elementami, które grupujemy w zbiory.
Implementacja drzewa z korzeniem
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
Implementacja drzewa z korzeniem
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).
Implementacja drzewa z korzeniem
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 drzewa z korzeniem
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;
Implementacja drzewa z korzeniem
Implementacja z uwzgl¦dnieniem heurystyk ª¡czenie wg wysoko±ci:
Link(x, y) 1 begin 2 ifh(x) > h(y)then 3 ojciec(y) := x 4 else begin 5 ojciec(x) := y; 6 ifh(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))
Implementacja drzewa z korzeniem
Implementacja z uwzgl¦dnieniem heurystyk kompresja drogi:
FindSet(x) 1 begin
2 if x <> ojciec(x)then
3 ojciec(x) := FindSet( ojciec(x) ); 4 returnojciec(x)
5 end;
Uwaga
Zauwa»my, »e po FindSet wysoko±¢ drzewa mo»e ulec zmianie (zmniejszeniu). Mimo to, nie uaktualniamy warto±ci h dla »ad-nego wierzchoªka. Utrzymywanie poprawnych warto±ci wysoko±ci drzew byªoby niepotrzebnie kosztowne. Zatem warto±ci h nale»y tak naprawd¦ interpretowa¢ jako górne ograniczenia wysoko±ci
Implementacja drzewa z korzeniem
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¦dnie-niem heurystyk 1 i 2 wynosi O(m log∗n).
log∗ = logarytm iterowany.
log∗ jest funkcj¡ bardzo wolno rosn¡c¡.
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.).
Przekroje
Denicje:
Ka»dy podzbiór S ⊆ V wyznaczaprzekró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¦dniazbió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 najmniejsza spo±ród wag wszystkich kraw¦dzi krzy»uj¡cych si¦ z tym przekrojem.
Przekroje
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).
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 ,
Przekroje
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.
Algorytm
Podsumowanie: szczegóªowa wersja algorytmu GenericMST algorytm Kruskala (por. ConnectedComponents).
MST-Kruskal(G, w) 1 begin
2 A := ∅;
3 forka»dy v ∈ Vdo
4 MakeSet(v);
5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end;
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end;
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 1
Algorytm przebieg
MST-Kruskal(G, w) 1 begin 2 A := ∅; 3 forka»dy v ∈ Vdo 4 MakeSet(v);5 posortuj E niemalej¡co wzgl¦dem wag w;
6 forka»da {u, v} ∈ E, w kolejno±ci niemalej¡cych wagdo
7 ifFindSet(u) <> FindSet(v)then
8 begin 9 A := A ∪ { {u, v} }; 10 Union(u, v) 11 end 12 returnA 13 end; @ v f 2 vf vf 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).
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.
Implementacja
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.
Algorytm
Inna realizacja ogólnego algorytmu algorytm Prima.
MST-Prim(G, w, r) 1 begin
2 Q := V;
3 forka»dy u ∈ Qdoklucz(u) := ∞; 4 klucz(r) := 0;
5 π[r] := ∞; 6 whileQ <> ∅do
7 begin
8 u := ExtractMin(Q);
9 forka»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;
MST-Prim(G, w, r) 1 begin
2 Q := V;
3 forka»dy u ∈ Qdoklucz(u) := ∞; 4 klucz(r) := 0;
5 π[r] := ∞;
6 whileQ <> ∅do
7 begin
8 u := ExtractMin(Q);
9 forka»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; @ v f 2 vf rvf 1
MST-Prim(G, w, r) 1 begin
2 Q := V;
3 forka»dy u ∈ Qdoklucz(u) := ∞; 4 klucz(r) := 0;
5 π[r] := ∞;
6 whileQ <> ∅do
7 begin
8 u := ExtractMin(Q);
9 forka»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; @ v f 2 vf rvf 1
MST-Prim(G, w, r) 1 begin
2 Q := V;
3 forka»dy u ∈ Qdoklucz(u) := ∞; 4 klucz(r) := 0;
5 π[r] := ∞;
6 whileQ <> ∅do
7 begin
8 u := ExtractMin(Q);
9 forka»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; @ v f 2 vf rvf 1
MST-Prim(G, w, r) 1 begin
2 Q := V;
3 forka»dy u ∈ Qdoklucz(u) := ∞; 4 klucz(r) := 0;
5 π[r] := ∞;
6 whileQ <> ∅do
7 begin
8 u := ExtractMin(Q);
9 forka»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; @ v f 2 vf rvf 1
MST-Prim(G, w, r) 1 begin
2 Q := V;
3 forka»dy u ∈ Qdoklucz(u) := ∞; 4 klucz(r) := 0;
5 π[r] := ∞;
6 whileQ <> ∅do
7 begin
8 u := ExtractMin(Q);
9 forka»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; @ v f 2 vf rvf 1
MST-Prim(G, w, r) 1 begin
2 Q := V;
3 forka»dy u ∈ Qdoklucz(u) := ∞; 4 klucz(r) := 0;
5 π[r] := ∞;
6 whileQ <> ∅do
7 begin
8 u := ExtractMin(Q);
9 forka»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; @ v f 2 vf rvf 1