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

Podobne dokumenty