Hledáme efektivní řešení úloh na grafu Mějme dán graf následující úlohy: G = ( V, E), chceme algoritmicky vyřešit Je daný vrchol t dosažitelný z vrcholu s? Pokud ano, jaká nejkratší cesta tyto vrcholy spojuje? Jaké má graf komponenty souvislosti? Obsahuje graf cyklus? Pokud ne, jak topologicky setřídíme vrcholy? Jak nalezneme silné komponenty? Jak nakreslíme graf jedním tahem? 1
Systematické průchody grafem 1. Prohledávání do šířky BFS (breadth-first search) 2. Prohledávání do hloubky DFS (depth-first search) Zobecnění průchodu stromem na obecný graf 2
Průchod do šířky ukázka b a c e f g h d 3
Průchod do šířky BFS(G,s): // G=(V,E) // inicializace, používáme pole D, P a frontu F for each v in V do D[v]:=-1; P[v]:=NULL; done D[s]:=0; F->push(s); while not F->empty() do v:=f->pop(); for each soused w vrcholu v do if D[w]=-1 then D[w]:=D[v]+1; P[w]=v; F->push(w); endif done done 4
Průchod do šířky Pozorování: v průběhu algoritmu obsahuje fronta F jen vrcholy, které mají D[v] rovno d nebo d+1, pro nějaké d D[v] obsahuje délku nejkratší cesty z s do v ( ) Časová složitost O V + E. odpovídá velikosti reprezentace G spojovým seznamem 5
Počítání komponent SpocitejKomponenty(G): // G=(V,E) - neorient. graf pocet_komp:=0; // modifikuj BFS, inicializuj D a P vně BFS2 for each v in V do D[v]:=-1; P[v]:=NULL; done for each v in V do if D[v]=-1 then BFS2(G,v); pocet_komp++; endif done return pocet_komp; 6
Průchod do hloubky ukázka b a c e f g h d 7
Průchod do hloubky DFS(G): // G=(V,E) for each v in V do stav[v]:=fresh; P[v]:=NULL; done time:=0; for each v in V do if stav[v]=fresh then DFS_Projdi(s); endif done DFS_Projdi(v): stav[v]:=open; time:=time+1; in[v]:=time; for each w in Sousede[v] do if stav[w]=fresh then P[w]:=v; DFS_Projdi(w); endif done stav[v]:=closed; time:=time+1; out[v]:=time; 8
Průchod do hloubky příklad č. 1 DFS stromy (DFS les): a (1,10) c (11,22) f (23,24) vstupní graf: a b c d b (2,3) e i (4,9) (5,8) d h (12,21) (13,20) e f g h j (6,7) k g (14,17) (15,16) l (18,19) i j k l 9
Průchod do hloubky příklad č. 2 vstupní graf: DFS strom: a (1,16) b a c b (2,11) c (12,15) e f d e (3,10) d (13,14) g h f h (4,7) (8,9) časová osa: a b e f g h g (5,6) c d 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 10
Typy hran při DFS pro orientovaný graf a b Určení typu pro hranu (u,v) podle stavu dosaženého vrcholu v: 1. v je FRESH stromová 2. v je OPEN zpětná 3. v je CLOSED dopředná nebo příčná c d 11
Typy hran při DFS pro orientovaný graf Pozorování: 1. Hrana (u,v) je stromová nebo dopředná právě když ( in[ u], out[ u] ) ( in[ v], out[ v] ) 2. Hrana (u,v) je zpětná právě když in[ u], out[ u] in[ v], out[ v] ( ) ( ) 3. Hrana (u,v) je příčná právě když in [ v] < out[ v] < in[ u] < out[ u] 12
Topologické uspořádání
Topologické uspořádání Věta: Orientovaný graf G nalezne zpětnou hranu. obsahuje cyklus právě když DFS Věta: Uspořádání vrcholů orientovaného acyklického grafu podle klesajících hodnot out[.] je topologické. G Důkaz: Je-li (u,v) stromová nebo dopředná, pak out [ u] > out[ v] Je-li (u,v) příčná, pak též out [ u] > out[ v] Tj., orientace hran v uvedeném uspořádání je korektní. 14
Hledání silných komponent C 2 C 1 kondenzace grafu: C1 C2 C 3 C 3 Při použití DFS potřebujeme komponenty projít v pořadí: 3 C2, Obecně, v opačném pořadí vůči nějakému topologickému uspořádání. C, C 1 15
Hledání silných komponent Pozorování: C 1 C 2 u v out [ u] > out[ v] Pro libovolné u C 1 a v C2. 16
Hledání silných komponent - algoritmus Vstup: orientovaný graf G G 1. vytvoř, graf opačně orientovaný ke 2. proveď DFS na a ulož posloupnost v sestupném pořadí 3. proveď DFS na, vrcholy procházej v pořadí podle klesajících hodnot G G out[.] G out[.] 17
Kreslení grafu jedním tahem Def.: Sled nazýváme tahem, pokud se v něm neopakují hrany (vrcholy se opakovat mohou). Def.: Eulerovský tah je každý tah, který obsahuje všechny hrany. Def.: Graf G nazýváme Eulerovský, pokud obsahuje alespoň jeden uzavřený Eulerovský tah. Věta: Souvislý graf G je Eulerovský právě když všechny jeho vrcholy mají sudý stupeň. 18
Sedm mostů města Královce 19
Eulerovský graf Euler(v): while existuje neprojitá hrana {v,w} do označ hranu {v,w}; Euler(w); vypiš v; done podobné jako DFS, vrcholy ale procházíme vícekrát 20
Pošťákův problém Jak obejít všechny ulice a vrátit se do výchozího bodu tak, aby celková trasa byla minimální? 21
Pošťákův problém Lemma: Nechť S je sled, který je optimálním řešením pošťákova problému v grafu G. Potom každá hrana grafu je v S obsažena maximálně dvakrát. H.. podgraf G, sestává z hran, které jsou v S dvakrát T.. množina vrcholů v G lichého stupně Lemma: H se skládá z T / 2 hranově disjunktních cest, jejichž konce leží v T. 22
Pošťákův problém - algoritmus 1. Určíme množinu T vrcholů lichého stupně. T / 2 2. Nalezneme cest, které spárují vrcholy v T a budou obsahovat co nejméně hran (využívá se algoritmus na hledání maximálního párování minimální ceny). Získáme tak graf H. 3. V multigrafu G+H nalezneme uzavřený Eulerovský graf. 23
Pošťákův problém 3 3 4 3 3 3 4 3 3 3 24