0 - Kolos
Transkrypt
0 - Kolos
Wykład 7 Algorytmy grafowe 1 Algorytmy grafowe i podstawowe algorytmy przeszukiwania Problem Definicje i własności Reprezentacja Przeszukiwanie wszerz (Breadth-First Search) Przeszukiwanie w głąb (Depth-First Search) Sortowanie topologiczne Literatura – Cormen, Leiserson, Rivest, “Wprowadzenie do algorytmów”, rozdział 23 2 Problem Wiele zjawisk może być opisanych poprzez binarne relacje pomiędzy obiektami: – Wszelkiego typu mapy drogowe i plany – Odsyłacze w stronach WWW Graf jest abstrakcyjną strukturą opisującą takie binarne relacje pomiędzy elementami. Bardzo dużo problemów można sprowadzić do rozwiązywania zadań grafowych: najkrótszej ścieżki, połączenia pomiędzy węzłami, minimalnego drzewa rozpinającego, etc. 3 Przykład zastosowania Siatka połączeń lotniczych • każdy wierzchołek reprezentuje miasto. • każda krawędź reprezentuje bezpośrednie połączenie lotnicze pomiędzy miastami. • pytanie o bezpośrednie połączenie = pytanie czy istnieje krawędź. • pytanie o połączenie = czy istnieje droga z A do B. • z połączeniami możemy powiązać koszty (grafy ważone), wtedy sensowne staje się pytanie o najtańsze połączenie z A do B. 4 Przykład: odnajdowanie właściwego połączenia w metrze Stacje są wierzchołkami Połączenia pomiędzy stacjami są krawędziami Najkrótsza droga= najmniejsza odległość, najmniejszy czas. Stacje, do których można dojechać (osiągalne). 5 Graf: definicja Grafem nazywamy parę G = (V,E), gdzie V = {v1, .. vn} jest zbiorem wierzchołków, E = {e1, .. em} jest zbiorem krawędzi. Krawędź ek = (vi ,vj) łączy dwa wierzchołki vi i vj ze zbioru V. Krawędzie mogą być skierowane lub nie (uporządkowane lub nieuporządkowane): eij: vi — vj lub eij: vi —> vj Graf G nazywamy skończonym jeśli |V| i |E| są skończone. Przez rozmiar grafu G rozumiemy |G| = |V| + |E|. 6 Przykłady Niech V = {1,2,3,4,5,6} 1 2 3 1 2 3 4 5 6 4 5 6 Graf skierowany Graf nieskierowany 7 Grafy z wagami (ważone) Grafem ważonym nazywamy graf dla którego każda krawędź ma przypisaną wagę (koszt) c(vi, vj) > 0. Każdy graf można uważać za graf ważony (dla każdej krawędzi przypisujemy wagę 1). Jeśli dwa wierzchołki nie są połączone to można je traktować jako połączone z wagą ∞. 2 1 2 6 8 4 4 5 1 5 7 3 6 Koszt ścieżki: suma kosztów poszczególnych krawędzi k c( p ) = ∑ c(vi −1 , vi ) i =1 8 Grafy skierowane W grafie skierowanym krawędzie są skierowane tj. e = (u,v) zaczyna się w u i kończy w v (v jest połączone z u). Dopuszczalne jest połączenie wierzchołka z samym sobą e = (u,u) Stopień wchodzący (indegree) din(v) dla wierzchołka v jest ilością krawędzi wchodzących do v. Odpowiednio stopień wychodzący (outdegree) dout(v) dla wierzchołka v jest ilością krawędzi wychodzących z v. Σdin(vi) = Σdout(vi) Ścieżka z u do v w grafie G = (V,E) o długości k jest sekwencją wierzchołków <u = v0,v1,…, vk = v> taką że dla i =1,…,k para (vi–1,vi) należy do E. 9 Grafy nieskierowane W grafie nieskierowanym krawędź e = (u,v) łączy wierzchołki u i v. Grafy nieskierowane nie mogą mieć połączeń wierzchołka z samym sobą Połączenie jest relacją symetryczną: jeśli e = (u,v) to u jest sąsiadem v oraz v jest sąsiadem u. Stopień wierzchołka d(v) jest ilością jego sąsiadów - Σd(vi) = 2|E|. Określenie ścieżki w grafie – tak samo jak dla grafu skierowanego. 10 Terminologia Cyklem nazywamy ścieżkę, która rozpoczyna się i kończy w tym samym wierzchołku. Grafem spójnym nazywamy nieskierowany graf dla którego istnieje ścieżka pomiędzy dwoma dowolnymi wierzchołkami (każdy wierzchołek jest osiągalny, z każdego innego wierzchołka). Grafem silnie spójnym nazywamy graf skierowany, dla którego dla każdych dwóch wierzchołków u i v istnieje droga z u do v oraz z v do u. Graf G’= (V’,E’) jest pod-grafem G = (V,E), jeśli G’ ⊆ G jeśli V’ ⊆ V oraz E’ ⊆ E. 11 Rozmiar grafu Istnieje co najwyżej |E| = O(|V|2) krawędzi w grafie. – Dowód: każdy węzeł może występować w co najwyżej |V| krawędziach. – Graf dla którego E| = |V|2 nazywamy kliką (każde dwa wierzchołki są połączone krawędzią). W każdym spójnym grafie jest co najmniej |E| ≥ |V|–1 krawędzi. – Dowód: przez indukcje dla |V|. Graf planarny (graf płaski) – graf, który da się narysować na płaszczyźnie tak, by łuki obrazujące krawędzie grafu nie przecinały się. Dla grafu planarnego mamy |E| = O(|V|). Dwa minimalne grafy, które nie są planarne, to K5 i K3,3. Twierdzenie Kuratowskiego (1930) mówi, że graf skończony jest planarny wtedy i tylko wtedy, gdy nie zawiera podgrafu homeomorficznego z grafem K5 ani z grafem K3,3. 12 Typy ścieżek Ścieżkę nazywamy prostą jeżeli żaden wierzchołek nie występuje w niej więcej niż raz • Składa się z różnych wierzchołków Ścieżkę nazywamy cyklem wtedy i tylko wtedy jeśli v0= vk. • Rozpoczyna się i kończy w tym samym wierzchołku! W ścieżkach zawierających cykl jako podścieżkę wierzchołki mogą pojawiać się kilkakrotnie. 13 Typy ścieżek - przykłady 1. {a,c,f,e} → ścieżka prosta, L = 3 2. {a,b,d,c,f,e} → ścieżka prosta, L = 5 3. {a,c,d,b,d,c,f,e} → ścieżka zawiera cykl {d,b,d} 4. {a,c,d,b,a} → cykl, L = 4 5. {a,c,f,e,b,d,c,a} → cykl, L = 7 14 Grafy a drzewa Drzewo jest to spójny graf, który nie zawiera cykli. Drzewo ma |E| =|V|–1 krawędzi. Następujące 3 własności są równoważne: 1. G jest drzewem. 2. G nie ma cykli; dodanie nowej krawędzi buduje cykl. 3. G jest spójny; po usunięciu dowolnego węzła przestaje taki być. Podobnie można podąć definicje drzewa skierowanego. 15 Reprezentacja grafu Mamy dwie standardowe reprezentacje grafów: 1. Lista sąsiedztwa: dla każdego węzła v tworzymy listę liniową Lv jego sąsiadów w grafie. Rozmiar takiej reprezentacji to: Θ(|V|+|E|). 2. Macierz sąsiedztwa: macierz |V| ×|V|, w której krawędź e = (u,v) jest reprezentowana przez niezerowe wejście (u,v). Rozmiar takiej reprezentacji to : Θ(|V|2). Lista sąsiedztwa jest wygodniejsza dla dla „rzadkich” grafów. Macierz sąsiedztwa jest wygodniejsza dla dla „gęstych” grafów. 16 Przykład: reprezentacja listą sąsiedztwa V = {1,2,3,4,5,6} E = {(1,2),(1,5),(2,5),(3,6)} 1 4 2 5 3 6 V Li 1 5 2 2 1 5 3 6 4 nul l 5 2 6 3 1 17 Przykład: reprezentacja macierzą sąsiedztwa V = {1,2,3,4,5,6} E = {(1,2),(1,5),(2,5),(3,6)} 1 4 2 5 3 6 1 2 1 1 2 1 3 4 5 1 1 6 A 3 4 5 1 1 6 1 1 Dla grafów nieskierowanych, A = AT 18 Porównanie reprezentacji lista sąsiedztwa bardziej zwarta niż macierz sąsiedztwa (dobra dla rzadkich grafów) stwierdzenie czy istnieje krawędź zajmuje więcej czasu macierz sąsiedztwa zawsze wymaga Θ(n2) pamięci często „marnujemy” dużo pamięci szybko możemy odnaleźć informację o krawędzi 19 Porównanie reprezentacji 0 macierz sąsiedztwa 8 2 9 1 7 3 4 6 5 Lista sąsiedztwa 0 8 1 2 3 7 2 1 4 8 3 1 4 4 2 3 5 3 6 6 5 7 7 1 6 8 0 2 9 1 8 5 9 0 1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 0 1 0 1 2 0 1 0 0 1 0 0 0 1 0 3 0 1 0 0 1 1 0 0 0 0 4 0 0 1 1 0 0 0 0 0 0 5 0 0 0 1 0 0 1 0 0 0 6 0 0 0 0 0 1 0 1 0 0 7 0 1 0 0 0 0 1 0 0 0 8 1 0 1 0 0 0 0 0 0 1 9 0 1 0 0 0 0 0 0 1 0 9 20 Porównanie reprezentacji pamięć Sprawdzenie istnienia połączenia (u, v) Odnajdowanie krawędzi rozpoczynających się w u Odnajdowanie krawędzi kończących się w v Odnalezienie wszystkich krawędzi Macierz sąsiedztwa Lista sąsiedztwa Lista krawędzi Θ(V2) Θ(V + E) Θ(E) Θ(1) Ο(outdegree[u]) Ο(E) Θ(V) Ο(outdegree[u]) Θ(E) Θ(V) Θ(E) Θ(E) Θ(V2) Θ(E) Θ(E) 21 Trawersowanie grafu Odnajdowanie połączeń – Mając dany graf i wierzchołek s w tym grafie. Odszukać drogi do wszystkich pozostałych wierzchołków tj. czy istnieje połączenie pomiędzy s i v – Najbardziej popularne są dwa algorytmy: • Breadth-First Search (BFS) – przeszukiwanie wszerz Odnajduje drogi (najkrótsze drogi) w grafach nieskierowanych. Odnajduje połączone wierzchołki. • Depth-First Search (DFS) – przeszukiwanie w głąb Odnajduje drogi w grafach nieskierowanych.. Odnajduje połączone wierzchołki. Przeprowadza topologiczne sortowanie w grafach skierowanych (liniowe uporządkowanie wierzchołków, w którym jeśli istnieje krawędź skierowana prowadząca od wierzchołka x do y, to x znajdzie się przed wierzchołkiem y. Innymi słowy, każdy wierzchołek poprzedza wszystkie te wierzchołki, do których prowadzą wychodzące od niego krawędzie). 22 BFS i problem najkrótszej ścieżki Mając dany dowolny wierzchołek s, BFS odwiedza wierzchołki w porządku rosnącym (względem odległości od s). W każdym kroku, BFS odwiedza wszystkie osiągalne wierzchołki o stałej odległości. W taki sposób, BFS odkrywa wszystkie drogi od s do innych wierzchołków. Co oznacza termin “odległość”? Ilość krawędzi w ścieżce od s. Przykład 0 s= 1 8 2 2 1 s 9 Wierzchołki odległe o1? 2, 3, 7, 9 1 1 7 3 6 1 4 2 Wierzchołki odległe o 2? 8, 6, 5, 4 1 5 2 2 Wierzchołki odległe o 3? 0 23 Algorytm BFS // flag[ ]: visited table 24 BFS przykład Lista sąsiedztwa 0 8 source 2 9 1 7 3 4 6 Visited Table (T/F) 0 F 1 F 2 F 3 F 4 F 5 F 6 F 7 F 8 F 9 F 5 Inicjalizacja tablicy (wszystko false) Q={ } Inicjalizacja kolejki Q (pusta) 25 Lista sąsiedztwa 0 8 source 2 9 1 7 3 4 6 Visited Table (T/F) 0 F 1 F 2 T 3 F 4 F 5 F 6 F 7 F 8 F 9 F 5 Oznaczamy 2 jako odwiedzone Q={ 2 } 26 Visited Table (T/F) 0 Neighbors 8 source 2 9 1 7 3 4 6 5 0 F 1 T 2 T 3 F 4 T 5 F 6 F 7 F 8 T 9 F Oznacz sąsiadów 1, 4, 8 jako odwiedzonych Q = {2} → Q = { 8, 1, 4 } Dequeue 2. Umieść wszystkich nieodwiedzonych sąsiadów 2 w kolejce 27 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 Neighbors 0 T 1 T 2 T 3 F 4 T 5 F 6 F 7 F 8 T 9 T 5 Q = { 8, 1, 4 } → Q = { 1, 4, 0, 9 } Oznacz nowo-odwiedzonych 0, 9 Dequeue 8. - umieść wszystkich nieodwiedzonych sąsiadów 8 w kolejce - 2 nie umieszczana w kolejce (już odwiedzona) 28 Visited Table (T/F) 0 2 9 1 7 3 4 T 1 T 2 T 3 T 4 T 5 F 6 F 7 T 8 T 9 T Neighbors 8 source 0 6 5 Oznacz nowo-odwiedzonych 3, 7 Q = { 1, 4, 0, 9 } → Q = { 4, 0, 9, 3, 7 } Dequeue 1. - dodaj do kolejki nieodwiedzonych sąsiadów1. - tylko 3 i 7 nie były jeszcze odwiedzone 29 Visited Table (T/F) 0 8 source 2 9 4 T 1 T 2 T 3 T 4 T 5 F 6 F 7 T 8 T 9 T Neighbors 1 7 3 0 6 5 Q = { 4, 0, 9, 3, 7 } → Q = { 0, 9, 3, 7 } Dequeue 4. - 4 nie posiada nieodwiedzonych sąsiadów! 30 Visited Table (T/F) 0 T 1 T 2 T 3 T 4 T 5 F 6 F 7 T 8 T 9 T Neighbors 0 8 source 2 9 1 7 3 4 6 5 Q = { 0, 9, 3, 7 } → Q = { 9, 3, 7 } Dequeue 0. - 0 nie ma nieodwiedzonych sąsiadów! 31 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 Neighbors 0 T 1 T 2 T 3 T 4 T 5 F 6 F 7 T 8 T 9 T 5 Q = { 9, 3, 7 } → Q = { 3, 7 } Dequeue 9. - 9 nie ma nieodwiedzonych sąsiadów! 32 Visited Table (T/F) 0 8 source Neighbors 2 9 1 7 3 4 6 5 0 T 1 T 2 T 3 T 4 T 5 T 6 F 7 T 8 T 9 T Oznaczamy 5 Q = { 3, 7 } → Q = { 7, 5 } Dequeue 3. - dodajemy 5 do kolejki. 33 Visited Table (T/F) 0 8 source 2 9 1 Neighbors 7 3 4 6 5 0 T 1 T 2 T 3 T 4 T 5 T 6 T 7 T 8 T 9 T Oznaczamy 6 Q = { 7, 5 } → Q = { 5, 6 } Dequeue 7. - dodajemy 6 do kolejki 34 Visited Table (T/F) 0 8 source 2 9 Neighbors 1 7 3 4 6 0 T 1 T 2 T 3 T 4 T 5 T 6 T 7 T 8 T 9 T 5 Q = { 5, 6} → Q = { 6 } Dequeue 5. - nie ma nieodwiedzonych sąsiadów 5 35 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 Neighbors 6 5 0 T 1 T 2 T 3 T 4 T 5 T 6 T 7 T 8 T 9 T Q={6}→Q={ } Dequeue 6. - brak nieodwiedzonych sąsiadów 6 36 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 0 T 1 T 2 T 3 T 4 T 5 T 6 T 7 T 8 T 9 T 5 Co osiągnęliśmy? Q={ } STOP!!! Q jest pusta!!! Wszystkie wierzchołki zostały odwiedzone. Istnieje droga od wierzchołka 2 Do wszystkich pozostałych w grafie 37 Złożoność czasowa BFS (z wykorzystaniem list sąsiedztwa) Przyjmijmy – n = ilość wierzchołków, m = ilość krawędzi. O(n + m) Każdy wierzchołek trafia do Q (enqueued i dequeued) co najwyżej raz. Każda iteracja zajmuje czas proporcjonalny do deg(v) + 1 ( “+1” ze względu na dequeue). 38 Czas wykonania W grafie o m krawędziach suma stopni wierzchołków wynosi? Σvertex v deg(v) = 2m Stąd całkowity czas działania (pętla while): O( Σvertex v (deg(v) + 1) ) = O(2m+n) = O(n+m) Suma wszystkich iteracji w pętli while! 39 Złożoność czasowa BFS (z wykorzystaniem macierzy sąsiedztwa) Przyjmijmy – n = ilość wierzchołków, m = ilość krawędzi. O(n2) Odnalezienie sąsiadów v wymaga przejrzenia wszystkich elementów w wierszu. Zajmuje to czas O(n). Sumując to dla wszystkich iteracji dostajemy O(n2). Dostajemy stąd, że, BFS w tej wersji ma złożoność O(n2) niezależnie od ilości krawędzi m. Dla listy sąsiedztwa mieliśmy O(n+m); Jeśli m=O(n2), (graf gęsty) to dostajemy O(n+m)=O(n2). 40 Odnajdowanie najlepszych dróg BFS pokazuje jedynie czy istnieje połączenie ze źródła s do pozostałych wierzchołków v. – Nie odnajduje ścieżki! – Potrzebujemy modyfikacji algorytmu odnajdującej ścieżki Jak to zrobić? – Nie wiemy które wierzchołki leżą na ścieżce dopóki nie dojdziemy do v! – Ale, dla pary {w,v}, wiemy czy w był odwiedzony z v. – Efektywne rozwiązanie: • Wykorzystać dodatkową tablicę pred[0..n-1] do zapamiętywania poprzedników dla każdego wierzchołka. • Pred[w] = v oznacza, że w został odwiedzony z v. 41 BFS + wyznaczanie ścieżek inicjujemy pred[v] Oznaczamy skąd przyszliśmy. 42 Przykład Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 Q={ 0 F - 1 F - 2 F - 3 F - 4 F - 5 F - 6 F - 7 F - 8 F - 9 F - Pred } 43 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 F - 1 F - 2 T - 3 F - 4 F - 5 F - 6 F - 7 F - 8 F - 9 F - Pred Q={ 2 } 44 Visited Table (T/F) 0 2 9 1 7 3 4 F - 1 T 2 2 T - 3 F - 4 T 2 5 F - 6 F - 7 F - 8 T 2 9 F - Neighbors 8 source 0 6 5 Pred Oznaczamy że przyszliśmy z 2. Q = {2} → Q = { 8, 1, 4 } Dequeue 2 45 Visited Table (T/F) 0 8 source 2 9 1 7 3 Neighbors 6 4 5 Q = { 8, 1, 4 } → Q = { 1, 4, 0, 9 } 0 T 8 1 T 2 2 T - 3 F - 4 T 2 5 F - 6 F - 7 F - 8 T 2 9 T 8 Pred Oznaczamy, że przyszliśmy z 8. Dequeue 8. 46 Visited Table (T/F) 0 2 9 1 7 3 4 T 8 1 T 2 2 T - 3 T 1 4 T 2 5 F - 6 F - 7 T 1 8 T 2 9 T 8 Neighbors 8 source 0 6 5 Pred Przyszliśmy z 1 Q = { 1, 4, 0, 9 } → Q = { 4, 0, 9, 3, 7 } Dequeue 1. 47 Visited Table (T/F) 0 8 Neighbors source 2 9 1 7 3 4 6 5 0 T 8 1 T 2 2 T - 3 T 1 4 T 2 5 F - 6 F - 7 T 1 8 T 2 9 T 8 Pred Q = { 4, 0, 9, 3, 7 } → Q = { 0, 9, 3, 7 } Dequeue 4. - 4 nie ma nieodwiedzonych sąsiadów! 48 Visited Table (T/F) 0 T 8 1 T 2 2 T - 3 T 1 4 T 2 5 F - 6 F - 7 T 1 8 T 2 9 T 8 Neighbors 0 8 source 2 9 1 7 3 4 6 5 Pred Q = { 0, 9, 3, 7 } → Q = { 9, 3, 7 } Dequeue 0. - 0 nie ma nieodwiedzonych sąsiadów! 49 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 Neighbors 5 0 T 8 1 T 2 2 T - 3 T 1 4 T 2 5 F - 6 F - 7 T 1 8 T 2 9 T 8 Pred Q = { 9, 3, 7 } → Q = { 3, 7 } Dequeue 9. - 9 nie ma nieodwiedzonych sąsiadów! 50 Visited Table (T/F) 0 1 0 2 8 3 T T T T Neighbors 4 source 2 9 5 1 6 7 7 3 4 8 6 5 9 T T F T T T 8 2 1 2 3 1 2 8 Pred Q = { 3, 7 } → Q = { 7, 5 } Dequeue 3. 51 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 Neighbors 6 5 0 T 8 1 T 2 2 T - 3 T 1 4 T 2 5 T 3 6 T 7 7 T 1 8 T 2 9 T 8 Pred Q = { 7, 5 } → Q = { 5, 6 } Dequeue 7. 52 Visited Table (T/F) 0 8 source 2 9 Neighbors 1 7 3 4 6 5 0 T 8 1 T 2 2 T - 3 T 1 4 T 2 5 T 3 6 T 7 7 T 1 8 T 2 9 T 8 Pred Q = { 5, 6} → Q = { 6 } Dequeue 5. 53 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 Neighbors 6 5 0 T 8 1 T 2 2 T - 3 T 1 4 T 2 5 T 3 6 T 7 7 T 1 8 T 2 9 T 8 Pred Q={6}→Q={ } Dequeue 6. 54 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 T 8 1 T 2 2 T - 3 T 1 4 T 2 5 T 3 6 T 7 7 T 1 8 T 2 9 T 8 Pred STOP!!! Q jest pusta!!! Q={ } Tablicę Pred można teraz wykorzystać do pokazania ścieżek! 55 Odnajdowanie ścieżek nodes visited from 0 8 1 2 2 - 3 1 4 2 5 3 6 7 7 1 8 2 9 8 Algorytm rekursywny Np: Path(0) →2,8,0 Path(6) →2,1,7,6 Path(1) →2,1 56 BFS Tree Ścieżki odnalezione przez BFS można przedstawić w postaci drzewa z korzeniem (nazywa się je BFS tree), gdzie początkowy wierzchołek jest korzeniem. BFS tree dla wierzchołka s=2. 57 Przeszukiwanie w głąb – Depth-First Search (DFS) DFS jest drugim popularnym algorytmem trawersowania grafów. – Idea jest podobna do przechodzenia pre-order (najpierw rodzic potem rekursywnie dzieci). DFS może pokazać informacje o grafie które trudno uzyskać przy BFS. – Np. czy w grafie istnieją cykle? 58 Algorytm DFS Algorytm DFS odwiedza sąsiadów korzystając z rekurencji. – Kiedykolwiek odwiedzamy v z u, rekursywnie odwiedzamy wszystkich nieodwiedzonych do tej pory sąsiadów v. Potem powracamy do u... – Zauważmy: możliwe jest, że w2 nie był odwiedzony kiedy rekursywnie odwiedzaliśmy w1, ale zostanie odwiedzony w czasie kiedy powrócimy z wywołania rekursywnego. u v w1 w3 w2 59 Algorytm DFS oznaczamy wszystkie nieodwiedzone wierzchołki Oznaczamy węzeł jako odwiedzony. Dla wszystkich nieodwiedzonych sąsiadów wywołaj rekursywnie RDFS(w) Można podobnie jak poprzednio oznaczać Ścieżki przy pomocy pred[ ]. 60 Przykład Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 F - 1 F - 2 F - 3 F - 4 F - 5 F - 6 F - 7 F - 8 F - 9 F - Pred 61 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 F - 1 F - 2 T - 3 F - 4 F - 5 F - 6 F - 7 F - 8 F - 9 F - Pred Oznaczamy 2 Jako odwiedzone RDFS( 2 ) teraz wywołujemy RDFS(8) 62 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 F - 1 F - 2 T - 3 F - 4 F - 5 F - 6 F - 7 F - 8 T 2 9 F - Pred 8 - odwiedzone RDFS( 2 ) RDFS(8) 2 już odwiedzone, wywołujemy RDFS(0) Rekursywne Pred[8] oznaczone wywołanie 63 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 T 8 1 F - 2 T - 3 F - 4 F - 5 F - 6 F - 7 F - 8 T 2 9 F - Pred Oznaczamy 0 jako odwiedzone i Pred[0] RDFS( 2 ) RDFS(8) RDFS(0) -> brak nieodwiedzonych sąsiadów, powrót do RDFS(8) Rekursywne wywołanie 64 powrót do 8 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 T 8 1 F - 2 T - 3 F - 4 F - 5 F - 6 F - 7 F - 8 T 2 9 F - Pred RDFS( 2 ) RDFS(8) teraz odwiedzamy 9 -> RDFS(9) Rekursywne wywołanie 65 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 T 8 1 F - 2 T - 3 F - 4 F - 5 F - 6 F - 7 F - 8 T 2 9 T 8 Pred Ozn. 9 i Pred[9] RDFS( 2 ) RDFS(8) RDFS(9) Rekursywne -> odwiedzamy 1, RDFS(1) wywołanie 66 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 T 8 1 T 9 2 T - 3 F - 4 F - 5 F - 6 F - 7 F - 8 T 2 9 T 8 Pred Oznaczamy 1 i Pred[1] RDFS( 2 ) RDFS(8) RDFS(9) Rekursywne RDFS(1) wywołanie odwiedzamy RDFS(3) 67 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 T 8 1 T 9 2 T - 3 T 1 4 F - 5 F - 6 F - 7 F - 8 T 2 9 T 8 Pred Oznaczamy 3 i Pred[3] RDFS( 2 ) RDFS(8) RDFS(9) Rekursywne RDFS(1) wywołanie RDFS(3) odwiedzamy RDFS(4) 68 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 F - 6 F - 7 F - 8 T 2 9 T 8 Pred RDFS( 2 ) Oznaczamy 4 i Pred[4] RDFS(8) RDFS(9) RDFS(1) Rekursywne RDFS(3) wywołanie RDFS(4) STOP wszyscy sąsiedzi 4 są już odwiedzeni wracamy do RDFS(3) 69 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 Powrót do 3 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 F - 6 F - 7 F - 8 T 2 9 T 8 Pred RDFS( 2 ) RDFS(8) RDFS(9) RDFS(1) Rekursywne RDFS(3) wywołanie odwiedzamy 5 -> RDFS(5) 70 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 F - 7 F - 8 T 2 9 T 8 Pred RDFS( 2 ) RDFS(8) Oznaczamy 5 i Pred[5] RDFS(9) RDFS(1) Rekursywne RDFS(3) wywołanie RDFS(5) 3 już odwiedzone, wracamy do 6 -> RDFS(6) 71 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 T 5 7 F - 8 T 2 9 T 8 Pred RDFS( 2 ) RDFS(8) Oznaczamy 6 i Pred[6] RDFS(9) RDFS(1) RDFS(3) Rekursywne RDFS(5) wywołanie RDFS(6) odwiedzamy 7 -> RDFS(7) 72 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 T 5 7 T 6 8 T 2 9 T 8 Pred RDFS( 2 ) RDFS(8) Oznaczamy 7 i Pred[7] RDFS(9) RDFS(1) RDFS(3) Rekursywne RDFS(5) wywołanie RDFS(6) RDFS(7) -> Stop – brak nieodwiedzonych sąsiadów 73 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 RDFS( 2 ) RDFS(8) RDFS(9) RDFS(1) RDFS(3) Rekursywne RDFS(5) wywołanie RDFS(6) -> Stop 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 T 5 7 T 6 8 T 2 9 T 8 Pred 74 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 RDFS( 2 ) RDFS(8) RDFS(9) RDFS(1) RDFS(3) Rekursywne RDFS(5) -> Stop wywołanie 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 T 5 7 T 6 8 T 2 9 T 8 Pred 75 Visited Table (T/F) 0 8 source 2 9 1 7 3 6 4 5 RDFS( 2 ) RDFS(8) RDFS(9) RDFS(1) RDFS(3) -> Stop 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 T 5 7 T 6 8 T 2 9 T 8 Pred Rekursywne wywołanie 76 Visited Table (T/F) 0 8 source 2 9 1 7 3 6 4 5 RDFS( 2 ) RDFS(8) RDFS(9) RDFS(1) -> Stop 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 T 5 7 T 6 8 T 2 9 T 8 Pred Rekursywne wywołanie 77 Visited Table (T/F) 0 8 source 2 9 1 7 3 6 4 5 RDFS( 2 ) RDFS(8) RDFS(9) -> Stop 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 T 5 7 T 6 8 T 2 9 T 8 Pred Rekursywne wywołanie 78 Visited Table (T/F) 0 8 source 2 9 1 7 3 6 4 5 RDFS( 2 ) RDFS(8) -> Stop 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 T 5 7 T 6 8 T 2 9 T 8 Pred Rekursywne wywołanie 79 Visited Table (T/F) 0 8 source 2 9 1 7 3 4 6 5 RDFS( 2 ) -> Stop 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 T 5 7 T 6 8 T 2 9 T 8 Pred Rekurencyjne wywołania zakończone 80 Odnajdowanie ścieżek przy pomocy DFS 0 Visited Table (T/F) 8 source 2 9 1 7 3 4 6 5 0 T 8 1 T 9 2 T - 3 T 1 4 T 3 5 T 3 6 T 5 7 T 6 8 T 2 9 T 8 Pred Np. Path(0) ->2 8 0 Path(6) ->2 8 9 1 3 5 6 Path(7) ->2 8 9 1 3 5 6 7 81 Drzewo DFS Otrzymujemy w taki sposób drzewo ścieżek (DFS-tree). Warto zauważyć, że jest ono znacznie “głębsze” niż dla BFS. Odzwierciedla on strukturę wywołań rekurencyjnych. - kiedy odwiedzamy sąsiada w wierzchołka v, dodajemy w jako dziecko v. - kiedy DFS powraca z wierzchołka v, powracamy do rodzica v. 82 Złożoność czasowa DFS (z zastosowaniem list sąsiedztwa) Nigdy nie odwiedzamy wierzchołka więcej niż raz. Musimy zatem sprawdzić wszystkie wierzchołki grafu. – Wiemy, że Σvertex v degree(v) = 2m, gdzie m jest ilością krawędzi. Dla każdego z wierzchołków zabiera to czas proporcjonalny do deg(v) + 1. Stąd czas wykonania DFS jest proporcjonalny do sumy ilości wierzchołków i krawędzi (tak jak dla BFS). – O(n + m) gdzie n – ilość wierzchołków, m – ilość krawędzi. Inny zapis: – O(|v|+|e|) |v| = ilość wierzchołków (n) |e| = ilość krawędzi (m) 83 Zastosowania grafów: połączenia G= P N Q L R O M s D E Jak stwierdzić czy dwa wierzchołki są połączone? C A F B K Czy A jest połączone z F? Czy A jest połączone z L? G H 84 Problem połączeń Graf nazywamy spójnym jeśli dla każdej pary wierzchołków istnieje droga łącząca je. niespójny spójny Jak można stwierdzić czy graf jest spójny? – Wykorzystać BFS lub DFS (wybierając dowolnie jakiś wierzchołek jako początek). – Jeśli odwiedziliśmy wszystkie wierzchołki to graf jest spójny. – Czas takiej procedury? O(n + m) 85 Spójne składowe 86 Spójne składowe Spójną składową grafu jest maksymalny spójny podgraf tego grafu. Zbiór spójnych składowych jest jednoznaczny dla każdego grafu. Przykład: poniższy graf można jednoznacznie przedstawić w postaci sumy 3 spójnych podgrafów: C1, C2 i C3. 87 Odnajdowanie spójnych składowych Odnajdujemy wszystkie wierzchołki połączone z “v” => tworzą jedną spójną składową Zwykły DFS 88 Złożoność czasowa dla każdego z podgrafów (i=1,2,…): O(ni + mi ) Stąd dla całego grafu: ∑ O ( n + m ) = O (∑ n + ∑ m ) = O ( n + m) i i i i i i i 89 Grafy skierowane W grafie skierowanym krawędzie są skierowane tj. e = (u,v) zaczyna się w u i kończy w v (v jest połączone z u). Dopuszczalne jest połączenie wierzchołka z samym sobą e = (u,u) Stopień wchodzący (in-degree) din(v) dla wierzchołka v jest ilością krawędzi wchodzących do v. Odpowiednio stopień wychodzący (outdegree) dout(v) dla wierzchołka v jest ilością krawędzi wychodzących z v. Σdin(vi) = Σdout(vi) Ścieżka z u do v w grafie G = (V,E) o długości k jest sekwencją wierzchołków <u = v0,v1,…, vk = v> taką że dla i =1,…,k para (vi–1,vi) należy do E. 90 Reprezentacja grafów skierowanych Można korzystać zarówno z macierzy sąsiedztwa, jak i z list sąsiedztwa. do z 91 Skierowane grafy acykliczne Skierowana ścieżka jest sekwencją wierzchołków (v0, v1, . . . , vk). Cykl skierowany jest skierowaną ścieżką o tożsamym początku i końcu. Graf skierowany jest acykliczny jeśli nie zawiera cykli skierowanych. 92 Indegree i Outdegree W wypadku grafów skierowanych nie można po prostu mówić o stopniu wierzchołka deg(v) Zamiast tego będziemy mówić o ilości krawędzi „wchodzących” Indegree(v) oraz „wychodzących” z wierzchołka Outdegree(v) Każdej krawędź arc(u,v) będzie liczona 2 razy: jako outdegree dla u oraz indegree dla v. ∑ vertex v indegree( v ) = ∑ outdegree( v ) = m vertex v 93 Obliczanie Indegree i Outdegree Outdegree łatwo obliczyć – Przeglądamy listę adj[v] i liczymy sąsiadów. Obliczanie Indegree – Rozpoczynamy od indegree[v]=0 dla każdego wierzchołka v. – Przeglądamy listy adj[v] dla każdego v. • Dla każdego odnalezionego wierzchołka: indegree[w]++; • Czas wykonania: O(n+m). 94 Przykład Indeg(2)? 2 3 6 8 0 2 7 Indeg(8)? 2 9 Outdeg(0)? 3 1 5 Ilość krawędzi? m = 13 4 outdegree? 13 indegree? 13 95 Zastosowanie grafów skierowanych Grafy skierowane często wykorzystuje się do reprezentacji zadań wzajemnie zależnych. – Tj. takich że każde następne może rozpocząć się dopiero po zakończeniu innego. Zależności takie mogą być modelowane poprzez krawędzie skierowane (arc). arc (i,j) oznacza, że zadanie j nie może rozpocząć się przed zakończeniem zadania i. i j Oczywiście, żeby praca się zakończyła taki graf nie może być cykliczny. 96 Sortowanie topologiczne liniowe uporządkowanie wierzchołków, w którym jeśli istnieje krawędź skierowana prowadząca od wierzchołka x do y, to x znajdzie się przed wierzchołkiem y. Innymi słowy, każdy wierzchołek poprzedza wszystkie te wierzchołki, do których prowadzą wychodzące od niego krawędzie. Wierzchołki w każdym grafie acyklicznym skierowanym można posortować topologicznie na jeden lub więcej sposobów. 3 6 8 0 2 1 7 9 5 np. 0 6 1 4 3 2 7 5 8 9 4 97 Algorytm sortowania topologicznego Zauważmy: – Punkt startowy musi posiadać indegree równe 0. – Jeśli takiego wierzchołka nie ma – gram nie jest acykliczny 1. Algorytm: Jeśli indegree dla wierzchołka wynosi zero można od niego zacząć (wypisujemy). 2. Jeśli wierzchołek i został wypisany to krawędzie wychodzące z niego nie są już potrzebne – możemy usunąć wszystkie krawędzie wychodzące z i oraz samo i. 3. Po usunięciu z grafu wierzchołka i pozostaje on acykliczny i można rozumowanie powtórzyć. 98 Topological Sort Znajdujemy punkt startowy redukujemy indegree(w) Wkładamy nowy start do kolejki Q 99 Przykład Indegree 3 6 8 0 2 1 7 9 5 4 0 6 1 2 2 7 3 1 4 0 0 1 1 2 2 8 3 1 4 5 4 1 5 9 5 2 6 3 6 1 7 8 7 1 8 9 8 2 9 2 9 5 2 start Q={0} OUTPUT: 0 100 Indegree 3 6 8 0 2 1 7 9 5 4 0 6 1 2 2 7 3 1 4 0 0 1 1 2 2 8 3 1 4 5 4 1 5 9 5 2 6 3 6 1 7 8 7 1 8 9 8 2 9 2 9 5 2 -1 -1 -1 Dequeue 0 Q = { } -> usuwamy krawędzie z 0 uaktualniamy indegree sąsiadów (6, 1, 4) OUTPUT: 0 101 Indegree 3 6 8 0 2 1 7 9 5 4 0 6 1 2 2 7 3 1 4 0 0 1 0 2 2 8 3 1 4 5 4 0 5 9 5 2 6 3 6 0 7 8 7 1 8 9 8 2 9 2 9 5 2 Q = { 6, 1, 4 } Wkładamy do kolejki wszystkie nowe punkty startowe OUTPUT: 0 102 Indegree 3 6 8 2 1 7 9 5 4 0 6 1 2 2 7 3 1 4 0 0 1 0 2 2 -1 8 3 1 -1 4 5 4 0 5 9 5 2 6 3 6 0 7 8 7 1 8 9 8 2 9 2 9 5 2 Dequeue 6 Q = { 1, 4 } usuwamy krawędzie.. uaktualniamy indegree sąsiadów (3, 2) OUTPUT: 0 6 103 Indegree 3 8 2 1 7 9 5 4 0 6 1 2 2 7 3 1 4 0 0 1 0 2 1 8 3 0 4 5 4 0 5 9 5 2 6 3 6 0 7 8 7 1 8 9 8 2 9 2 9 5 2 Q = { 1, 4, 3 } Enqueue 3 OUTPUT: 0 6 104 Indegree 3 8 2 1 7 9 5 4 0 6 1 2 2 7 3 1 4 0 0 1 0 2 1 8 3 0 4 5 4 0 5 9 5 2 6 3 6 0 7 8 7 1 8 9 8 2 9 2 9 5 2 -1 Dequeue 1 Q = { 4, 3 } OUTPUT: 0 6 1 105 Indegree 3 8 2 7 9 5 4 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 2 6 3 6 0 7 8 7 1 8 9 8 2 9 2 9 5 2 Dequeue 1 Q = { 4, 3, 2 } Enqueue 2 OUTPUT: 0 6 1 106 Indegree 3 8 2 7 9 5 4 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 2 6 3 6 0 7 8 7 1 8 9 8 2 9 2 9 5 2 -1 Dequeue 4 Q = { 3, 2 } OUTPUT: 0 6 1 4 107 Indegree 3 8 2 7 9 5 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 1 6 3 6 0 7 8 7 1 8 9 8 2 9 2 9 5 2 -1 Dequeue 3 Q = { 2 } OUTPUT: 0 6 1 4 3 108 Indegree 8 2 7 9 5 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 1 6 3 6 0 7 8 7 1 8 9 8 1 9 2 9 5 2 Dequeue 3 Q = { 2 } OUTPUT: 0 6 1 4 3 109 Indegree 8 2 7 9 5 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 1 6 3 6 0 7 8 7 1 8 9 8 1 9 2 9 5 2 -1 -1 Dequeue 2 Q = { } OUTPUT: 0 6 1 4 3 2 110 Indegree 8 7 9 5 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 0 6 3 6 0 7 8 7 0 8 9 8 1 9 2 9 5 2 Dequeue 2 Q = { 7, 5 } Enqueue 7, 5 OUTPUT: 0 6 1 4 3 2 111 Indegree 8 7 9 5 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 0 6 3 6 0 7 8 7 0 8 9 8 1 9 2 9 5 2 -1 Dequeue 7 Q = { 5 } OUTPUT: 0 6 1 4 3 2 7 112 Indegree 8 9 5 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 0 6 3 6 0 7 8 7 0 8 9 8 0 9 2 9 5 2 Dequeue 7 Q = { 5, 8 } OUTPUT: 0 6 1 4 3 2 7 113 Indegree 8 9 5 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 0 6 3 6 0 7 8 7 0 8 9 8 0 9 2 9 5 2 -1 Dequeue 5 Q = { 8 } OUTPUT: 0 6 1 4 3 2 7 5 114 Indegree 8 9 5 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 0 6 3 6 0 7 8 7 0 8 9 8 0 9 1 9 5 2 Dequeue 5 Q = { 8 } OUTPUT: 0 6 1 4 3 2 7 5 115 Indegree 8 9 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 0 6 3 6 0 7 8 7 0 8 9 8 0 9 1 9 5 2 -1 Dequeue 8 Q = { } OUTPUT: 0 6 1 4 3 2 7 5 8 116 Indegree 8 9 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 0 6 3 6 0 7 8 7 0 8 9 8 0 9 0 9 5 2 Dequeue 8 Q = { 9 } Enqueue 9. OUTPUT: 0 6 1 4 3 2 7 5 8 117 Indegree 9 Dequeue 9 Q = { } STOP – brak sąsiadów 0 6 1 2 2 7 3 1 4 0 0 1 0 2 0 8 3 0 4 5 4 0 5 9 5 0 6 3 6 0 7 8 7 0 8 9 8 0 9 0 9 5 2 OUTPUT: 0 6 1 4 3 2 7 5 8 9 118 3 6 8 0 2 1 7 9 5 4 OUTPUT: 0 6 1 4 3 2 7 5 8 9 119 Złożoność dla sortowania topologicznego Nigdy nie odwiedzamy wierzchołka więcej niż raz. Dla każdego wierzchołka, – Sprawdzamy wszystkie wychodzące krawędzie, – Co zabiera czas proporcjonalny do outdegree(v) + 1. Jeśli zsumujemy to dla wszystkich wierzchołków to dostaniemy czas O(n + m). 120