• Nie Znaleziono Wyników

[wersja do druku]

N/A
N/A
Protected

Academic year: 2021

Share "[wersja do druku]"

Copied!
13
0
0

Pełen tekst

(1)

Podstawowe algorytmy grafowe

i ich zastosowania

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

(2)
(3)

1 Wst¦p

1.1 Przeszukiwanie grafu

Przeszukiwanie (przegl¡danie) grafu = systematyczne przechodzenie wzdªu» jego kraw¦dzi w celu odwiedzenia wszystkich wierzchoªków.

• Sªu»y m.in. do zbierania informacji o strukturze grafu.

• Algorytmy grafowe cz¦sto zaczyna si¦ od przeszukania wej±ciowego grafu.

• Wiele bardziej zaawansowanych algorytmów grafowych jest modykacj¡ podstawowych algorytmów przeszukiwania.

Dwie metody przeszukiwania grafu: • w gª¡b (ang. depth-rst search, DFS), • wszerz (ang. breadth-rst search, BFS).

W obu metodach b¦dziemy iterowa¢ po s¡siadach danego wierzchoªka. Dlatego najwygod-niejsz¡ reprezentacj¡ grafu s¡ listy s¡siedztwa.

Oznaczenia: Adj = tablica list s¡siedztwa; dla u ∈ V , Adj[u] = lista s¡siadów u w grae G.

Uwaga. Iteracj¦ po s¡siadach danego wierzchoªka mo»na ªatwo zrealizowa¢ równie» na macierzy s¡siedztwa. Jest to jednak bardziej kosztowne w sensie zªo»ono±ci obliczeniowej.

2 DFS

2.1 Przeszukiwanie grafu w gª¡b

Ustalmy graf niezorientowany G = (V, E).

Z ustalonego wierzchoªka ¹ródªowego w si¦gamy coraz gª¦biej w graf, je»eli jest to tylko mo»liwe.

• badamy wszystkie niezbadane dot¡d kraw¦dzie ostatnio odwiedzonego wierzchoªka v, • gdy wszystkie kraw¦dzie v s¡ zbadane, wracamy do wierzchoªka, z którego v zostaª

odwiedzony,

• proces kontynuujemy dopóki wszystkie wierzchoªki osi¡galne z wierzchoªka ¹ródªowego wnie zostan¡ odwiedzone.

Je»eli po powy»szym procesie pozostanie jakikolwiek nie odwiedzony wierzchoªek u, kontynu-ujemy przeszukiwanie traktuj¡c go jako nowy wierzchoªek ¹ródªowy.

Caªy proces powtarzamy, a» wszystkie wierzchoªki w grae zostan¡ odwiedzone. Nale»y zatem zapami¦tywa¢ stany, w jakich znajduj¡ si¦ w danej chwili wierzchoªki. Do zapisania aktualnego stanu wierzchoªka u»ywamy jednego z trzech kolorów:

• biaªy  wszystkie wierzchoªki na pocz¡tku;

• wierzchoªek odwiedzany po raz pierwszy kolorujemy na szaro;

• wierzchoªek przetworzony (= lista jego s¡siadów jest caªkowicie zbadana) kolorujemy na czarno.

(4)

Uwaga. Tak naprawd¦ w najprostszej implementacji wystarcz¡ dwa stany: nieodwiedzony i odwiedzony. Jednak dokªadniejsze rozró»nienie stanów pozwala lepiej zrozumie¢ ide¦ DFS oraz jest wykorzystywane w niektórych zastosowaniach.

DFS-Visit(G, u) 1 begin

2 kolor(u) := szary; 3 forka»dy v ∈ Adj[u]do

4 ifkolor(v) = biaªythen DFS-Visit(G, v); 5 kolor(u) := czarny;

6 end;

Przebieg algorytmu dla u = 1

@ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6

(5)

@ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6

(6)

@ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6 @ @ @ @ @ @ w g wg wg w g wg wg 1 2 3 4 5 6

Zauwa»my, »e po wywoªaniu DFS-Visit dla wierzchoªka u wierzchoªki, które nie s¡ osi¡galne z u pozostan¡ nieodwiedzone (biaªe). Aby zatem przejrze¢ caªy graf, nale»y wywoªywa¢ DFS-Visit dopóki b¦d¡ biaªe wierzchoªki.

(7)

DFS(G) 1 begin

2 forka»dy u ∈ V(G)do 3 kolor(u) := biaªy; 4 forka»dy u ∈ V(G)do 5 ifkolor(u) = biaªythen

6 DFS-Visit(G, u);

7 end;

• Zªo»ono±¢ czasowa: O(|V | + |E|): odwiedzamy ka»dy wierzchoªek i (dwukrotnie!) ka»d¡ kraw¦d¹.

• Zªo»ono±¢ pami¦ciowa: O(|V |): przechowywanie kolorów, przechowywanie wierz-choªków na stosie rekurencji.

3 Zastosowania DFS

3.1 Badanie spójno±ci

Podstawowe zastosowania:

• Sprawdzanie spójno±ci grafu.

• Wyznaczanie skªadowych spójno±ci grafu.

Zauwa»my, »e w procedurze DFS wywoªujemy DFS-Visit dokªadnie tyle razy, ile jest skªad-owych spójno±ci w grae G.

W szczególno±ci, gdy graf jest spójny, DFS-Visit zostanie wywoªana dokªadnie raz przez procedur¦ DFS.

Nietrudno uzupeªni¢ procedur¦ DFS o kod zliczaj¡cy skªadowe spójno±ci, jak równie» przyp-isuj¡cy wierzchoªkom numer skªadowej.

3.2 DFS - inne zastosowania

Inne zastosowania:

• Wyznaczanie silnie spójnych skªadowych (w wersji dla grafu skierowanego). • Sortowanie topologiczne grafu zorientowanego (bez zorientowanych cykli). • Generowanie labiryntów.

• Znajdowanie drogi w labiryncie.

Zainteresowanych odsyªamy do literatury (patrz te» dodatkowe materiaªy do wykªadu i zaj¦¢ laboratoryjnych).

4 BFS

4.1 Przeszukiwanie grafu wszerz

Z ustalonego wierzchoªka ¹ródªowego s przegl¡damy kolejne wierzchoªki z niego osi¡galne. • wierzchoªki w odlegªo±ci (=najmniejszej liczbie kraw¦dzi) k od ¹ródªa s¡ odwiedzane

(8)

• granica mi¦dzy wierzchoªkami odwiedzonymi i nieodwiedzonymi jest przekraczana jed-nocze±nie na caªej jej szeroko±ci.

Je»eli po powy»szym procesie pozostanie jakikolwiek nie odwiedzony wierzchoªek u, kontynu-ujemy przeszukiwanie traktuj¡c go jako nowy wierzchoªek ¹ródªowy.

Caªy proces powtarzamy, a» wszystkie wierzchoªki w grae zostan¡ odwiedzone.

Ka»dy wierzchoªek posiada jeden z 3 kolorów: biaªy, szary lub czarny (podobnie jak w DFS). Na pocz¡tku wszystkie wierzchoªki s¡ biaªe.

Wierzchoªki szare s¡ przechowywane w kolejce FIFO. Po jej opuszczeniu kolorujemy je na czarno.

4.2 Kolejka FIFO

Kolejka FIFO Q jest dynamiczn¡ struktur¡ danych w formie ci¡gu, do której mo»na doª¡czy¢ skªadnik tylko w jednym ko«cu (na ko«cu kolejki - tail), a usun¡¢ tylko w drugim ko«cu (na pocz¡tku kolejki - head). Mamy zatem dwie podstawowe operacje:

• Enqueue(Q, v) = dodanie elementu v na ko«cu kolejki, • Dequeue(Q) = usuni¦cie elementu z pocz¡tku kolejki. Dodatkowo wykorzystamy operacj¦

• Head(Q) = zwrócenie elementu z pocz¡tku kolejki (bez usuwania go).

Uwaga. Kolejk¦ implementujemy przy u»yciu struktur wska¹nikowych. Mo»na te» zasy-mulowa¢ jej dziaªanie na zwykªej (statycznej) tablicy, albo wykorzysta¢ gotowe struktury bib-lioteczne (np. queue biblioteki STL w C++).

4.3 Algorytm BFS-Visit(G, s) 1 begin 2 kolor(s) := szary; 3 Q := {s}; 4 whileQ <> ∅ do begin 5 u := Head(Q);

6 forka»dy v ∈ Adj[u]do 7 ifkolor(v) = biaªythen begin

8 kolor(v) := szary; 9 Enqueue(Q, v) 10 end; 11 Dequeue(Q); 12 kolor(u) := czarny 13 end 14 end

Przebieg algorytmu dla s = 1

@ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q:

(9)

@ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 1 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 1 2 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 1 2 5 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 1 2 5 4 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 2 5 4 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 5 4 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 5 4 3 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 5 4 3 6 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 4 3 6 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 3 6 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 6

(10)

@ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q:

Zauwa»my, »e po wywoªaniu BFS-Visit dla wierzchoªka u wierzchoªki, które nie s¡ osi¡galne z u pozostan¡ nieodwiedzone (biaªe). Aby zatem przejrze¢ caªy graf, nale»y wywoªywa¢ BFS-Visit dopóki b¦d¡ biaªe wierzchoªki.

Peªen przebieg algorytmu BFS jest realizowany przez poni»sz¡ procedur¦: BFS(G)

1 begin

2 forka»dy u ∈ V(G)do 3 kolor(u) := biaªy; 4 forka»dy u ∈ V(G)do 5 ifkolor(u) = biaªythen

6 BFS-Visit(G, u);

7 end;

• Zªo»ono±¢ czasowa: O(|V | + |E|) (analogicznie jak dla DFS). • Zªo»ono±¢ pami¦ciowa: O(|V |) (przechowywanie kolorów, kolejka).

5 Zastosowania BFS

5.1 Najkrótsza droga

Zastosowanie: znajdowanie najkrótszej drogi pomi¦dzy wierzchoªkami s i v. Modykacja procedury BFS-Visit: przechowywanie wektora poprzedników π. Tj. poprzednikiem wierzchoªka v na najkrótszej drodze z s do v jest wierzchoªek π[v]; poprzednikiem wierzchoªka π[v] jest wierzchoªek π[π[v]]...

Przygotowanie: forka»dy u ∈ V(G)do begin kolor(u) := biaªy; π[u] := ∞ end; 5.2 Zmodykowany BFS BFS-Visit(G, s) 1 begin 2 kolor(s) := szary; 3 Q := {s}; 4 whileQ <> ∅ do begin 5 u := Head(Q);

6 forka»dy v ∈ Adj[u]do 7 ifkolor(v) = biaªythen begin

8 kolor(v) := szary; 9 π[v] := u; 10 Enqueue(Q, v) 11 end; 12 Dequeue(Q); 13 kolor(u) := czarny 14 end 15 end

(11)

Przebieg algorytmu dla s = 1 w π[w] 1 ∞ 2 ∞ 3 ∞ 4 ∞ 5 ∞ 6 ∞ @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: w π[w] 1 ∞ 2 ∞ 3 ∞ 4 ∞ 5 ∞ 6 ∞ @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 1 w π[w] 1 ∞ 2 1 3 ∞ 4 ∞ 5 ∞ 6 ∞ @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 1 2 w π[w] 1 ∞ 2 1 3 ∞ 4 ∞ 5 1 6 ∞ @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 1 2 5 w π[w] 1 ∞ 2 1 3 ∞ 4 1 5 1 6 ∞ @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 1 2 5 4 w π[w] 1 ∞ 2 1 3 ∞ 4 1 5 1 6 ∞ @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 2 5 4 w π[w] 1 ∞ 2 1 3 ∞ 4 1 5 1 6 ∞ @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 5 4 w π[w] 1 ∞ 2 1 3 5 4 1 5 1 6 ∞ @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 5 4 3

(12)

w π[w] 1 ∞ 2 1 3 5 4 1 5 1 6 5 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 5 4 3 6 w π[w] 1 ∞ 2 1 3 5 4 1 5 1 6 5 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 4 3 6 w π[w] 1 ∞ 2 1 3 5 4 1 5 1 6 5 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 3 6 w π[w] 1 ∞ 2 1 3 5 4 1 5 1 6 5 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 6 w π[w] 1 ∞ 2 1 3 5 4 1 5 1 6 5 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6 Q: 5.3 Odczytanie dróg

Po wykonaniu BFS-Visit(G, s) w wektorze π zakodowane s¡ najkrótsze drogi z wierzchoªka ¹ródªowego s do wszystkich wierzchoªków w osi¡galnych z s. W naszym przykªadzie s = 1:

w π[w] 1 ∞ 2 1 3 5 4 1 5 1 6 5 @ @ @ @ v f 1 vf2 vf3 v f 4 5vf vf6

Np. najkrótsza droga z s = 1 do 6 to: 6 ← π[6] ← π[π[6]], czyli

6 ← 5 ← 1.

A najkrótsza droga z s = 1 do 3 to: 3 ← π[3] ← π[π[3]], czyli

3 ← 5 ← 1.

Odczytanie i wypisanie drogi z s do v od ko«ca mo»e by¢ zrealizowane przez poni»szy pseudokod:

(13)

PrintPathRev(s, v) 1 begin

2 ifs = vthenwypisz(v)

3 else ifπ[v] = ∞thenwypisz('Nie ma drogi') 4 else begin 5 whilev <> sdo begin 6 wypisz(v); 7 v := π[v] 8 end; 9 wypisz(s) 10 end 11 end;

Jednak bardziej naturalnym byªoby wypisanie drogi z s do v od pocz¡tku. Do tego mo»e posªu»y¢ poni»sza elegancka procedura rekurencyjna:

PrintPath(s, v) 1 begin

2 ifs = vthenwypisz(v)

3 else ifπ[v] = ∞thenwypisz('Nie ma drogi') 4 else begin 5 PrintPath(s, π[v]); 6 wypisz(v) 7 end 8 end; 5.4 Podsumowanie

Je»eli interesuje nas najkrótsza droga pomi¦dzy dwoma ustalonymi wierzchoªkami s i t, to: • uruchamiamy BFS-Visit dla wierzchoªka s,

• odczytujemy drog¦ z s do t z wektora π.

Wektor π b¦dzie zawieraª, jako skutek uboczny, najkrótsze drogi z s do wszystkich wierz-choªków osi¡galnych z s (nie tylko t!). Wyliczania tej nadmiarowej informacji nie da si¦ tu unikn¡¢.

Zauwa»my, »e tu przez najkrótsz¡ drog¦ rozumieli±my drog¦ o najmniejszej liczbie kraw¦dzi. Mo»na rozwa»a¢ grafy, w których kraw¦dzie maj¡ dªugo±¢ (lub inny koszt) i poszukiwa¢ najkrótszych dróg wzgl¦dem tego parametru.

Cytaty

Powiązane dokumenty

[r]

Mediana pierwszej z nich to dolny kwartyl (pierwszy kwartyl), a dru- giej to górny kwartyl (trzeci kwartyl). minimaln¡ lub maksymaln¡).. Je»eli w zestawie danych wyst¦puje

b¦dzie ci¡giem nie- zale»nych zmiennych losowych o

W momencie napotkania tej instrukcji wykonywanie funkcji jest zako«czone, a odpowiednia warto±¢ (która oczywi±cie mo»e by¢ ró»na dla ró»nych return) jest podstawiana w

Jak i poprzednio zakªada si¦, »e zbiór jednopunktowy jest domkni¦ty przestrze« jest typu T1.. Przestrze« z topologi¡ o tej wªasno±ci nazywa si¦

Suma dwóch zbiorów przeliczalnych jest zbiorem przeliczalnym. Je eli który z nich jest zbiorem pustym, to twierdzenie jest oczywiste. Wnioski.. 1) Suma ka dej sko czonej ilo

Wielomian stopnia nieparzystego posiada przynajmniej jeden pierwiastek rzeczywisty..

Równanie rz¦du pierwszego nierozwi¡zywalne wzgl¦dem pochodnych. Tutaj b¦dziemy rozwa»a¢ równanie postaci ogólnej F (x, y, y 0 )