Teorie grafů Základní informace V této výukové jednotce se student seznámí s matematickým pojetím grafů a na konkrétních příkladech si vyzkouší vybrané algoritmy pro hledání v grafech. Výstupy z výukové jednotky Student se seznámí se základními charakteristikami grafů, bude umět zapsat reprezentaci grafu pomocí matic a spojových seznamů. Seznámí se se základními úlohami nad grafy a bude umět pomocí algoritmů najít nejkratší cestu v grafu.. Motivace Grafy jsou jedním ze základních pojmů informatiky a zároveň se jedná o velmi užitečnou a praktickou pomůcku k řešení nejrůznějších druhů problémů. Graf je možné si představit jako zjednodušení reálného světa, kdy daný problém znázorníme pomocí bodů a čar, které je spojují. Tyto body se nazývají uzly (vrcholy) grafu a spojnice mezi nimi se nazývají hrany grafu. Graf může reprezentovat nějaký problém, síť, uspořádání prvků, algoritmus a podobně. Grafy mají využití nejen v informatice a matematice, ale také např. ve fyzice, v chemii, v elektrotechnice, v ekonomii nebo v sociologii. Grafy můžeme využít k hledání nejkratší cesty mezi dvěma místy, k řešení úloh umělé inteligence při hraní šachů, k optimalizaci elektrizační soustavy a k řešení mnohých dalších úloh. Hrana má vždy počátek a konec v nějakém uzlu. Většinou jsou počáteční a koncové uzly různé, pokud ale nejsou, hovoříme o tzv. smyčce. Teoreticky může vést mezi dvěma uzly i více hran v tom případě hovoříme o multigrafu..2 Základní pojmy Pro úspěšnou manipulaci s grafy je vhodné je definovat. efinice je velmi jednoduchá, protože graf obsahuje pouze uzly a hrany. Grafem G tedy nazýváme dvojici množin V a H, kde množina V označuje množinu uzlů grafu a H množinu hran grafu. Formálně G = (V, H). Někdy se ještě k této dvojici přidává třetí množina, tzv. incidenční funkce f, která definuje počáteční a koncové uzly pro každou hranu. Potom můžeme graf zapsat jako trojici G = (V, H, f). Pro grafickou reprezentaci grafů budeme používat následující notaci: vrcholy (uzly) grafu znázorňujeme kroužkem nebo tečkou, hrany grafu jsou zobrazeny úsečkou, směr hrany je pak vyjádřen orientací, tedy šipkou z počátečního uzlu do uzlu koncového. O uzlech spojených hranou, říkáme, že spolu sousedí, jsou to tedy sousední uzly. Ve vztahu uzel - hrana se používá pojem incidence. Úloha: Zadefinujte graf z náledujícího obrázku:
Řešení: V = {,, E, F} H = {a, b, c, d, e} ρ(a) = {, }, ρ( (b) = {, E}, ρ(c) = {, E}, ρ(d) = {, F}, ρ(e) = {E, F} efinice: Je-li x = y, pak hrana H je označována jako smyčka..3 Vlastnosti grafů efinice: Prostý graf je takový orientovaný nebo neorientovaný graf, v němž je násobnost každé hrany nejvýše rovna jedné. (Hrany h a h 2 nazveme násobné, jestliže f(h ) = f(h 2 ) = (x,y) ). Příklad grafu, který obsahuje násobné hrany (vlevo) a příklad prostého grafu (vpravo): efinice: Jednoduchý graf je takový orientovaný nebo neorientovaný graf, který neobsahuje smyčky. Obrázek vlevo znázorňuje graf, který není jednoduchý, neboť obsahuje smyčky u vrcholů a a b. Graf vpravo již jednoduchý je: efinice: Úplný graf je takový orientovaný nebo neorientovaný graf, ve kterém mezi každými dvěma uzly existuje právě jedna hrana. Příklady úplných grafů na až 4 vrcholech: 2
efinice: Neorientovaný graf je takový graf, ve kterém platí, ž eke každé hraně h pro níž platí f( (h) =(x,y), existuje hrana h taková, že f(h ) =(y,x). V opačném případě se jedná o orientovaný graf. Orientovaný graf můžeme znázornit obrázkem, kde vrcholy znázorníme jako kolečka a hrany jako šipky vedoucí mezi těmito kolečky. Příklad takového grafu je na následujícím obrázku, kde je znázorněn graf G = (V, H), kde V = {,,,,E,F} a H = {(, ), (, ) ), (, ), (, ), (, ), (, ), (, ), (E, F)}. Neorientovaný graf se znázorňuje podobně jako orientovaný, na konci čar, které představují hrany však nekreslíme šipky. Příklad neorientovaného grafu je uveden na následujícím obrázku. Jedná se o graf G = (V, H), kde V = {,,,,E,F } a H = {(, ), (, ), (, ), (, ),,(E,F)}. Poznámka: U orientovaného grafu říkáme, že hrana (u, v) vychází z vrcholu u a vstupuje do vrcholu v. U neorientovaného grafu říkáme, že hrana (u, v) je incidentní s vrcholy u a v. efinice: Stupeň vrcholu v neorientovaném grafu je počet hran, které jsou s tímto vrcholem incidentní. V orientovaném grafu je vstupní stupeň vrcholu počet hran, které do daného vrcholu vstupují, výstupní stupeň vrcholu počet hran, které z daného vrcholy vystupují a stupeň vrcholu je součet jeho vstupního a výstupního stupně. efinice: Graf, kde jsou hrany, respektive vrcholy, zobrazeny do nějaké předem dané množiny, ze které se vybírá ohodnocení, se nazývá hranově ohodnocený graf (resp. vrcholově ohodnocený graf). Příslušné zobrazení se nazývá ohodnocení.. efinice: Graf G = (V, E ) je podgrafem grafu G = (V, H) ), jestliže V V a H H. Pro danou množinu V V je podgraf grafu G indukovaný množinou vrcholů V definován jako graf G = (V, H ), kde H = {(u, v) H u, v V }. efinice: Sled délky k v grafu G z vrcholu v do vrcholu vk je konečná posloupnost v, h, v, h 2, v 2,..., v k-, h k, v k, kde k, ve které se vždy střídají vrcholy a hrany a pro každé j =,..., k platí, že hrana h j spojuje vrchol v j- s vrcholem v j. efinice: Tah v grafuje sled, v němž se neopakují hrany. efinice: esta v grafu je sled, v němž se neopakují vrcholy. 3
efinice: yklus je tah v, v,..., v k, kde k >, v = vk a všechny vrcholy kromě v a v k jsou navzájem různé. efinice: V případě neorientovaného grafu se cyklu též říká kružnice. efinice: Vrchol y je dostupný z vrcholu x, jestliže existuje sled kde v = x a v k = y. efinice: Graf G se nazývá souvislým, jestližee pro každé dva vrcholy x a y existuje v grafu G cesta začínající ve vrcholu x a končící ve vrcholu y. efinice: Graf bez kružnic se nazývá les. efinice: Souvislý les se pak nazývá strom. Strom je tedy minimální souvislý graf bez kružnic. Odebráním libovolné hrany a přidáním libovolné hrany vznikne kružnice. Níže je příklad stromu: se stane nesouvislým efinice: inární strom je strom, který má pro každý uzel nejvýše dva následníky. efinice: Kořenový strom je orientovaný graf, ve kterém je vyznačen jeden vrchol nazvaný kořen. o kořene nevede žádná (orientovaná) hrana, má tedy vstupní stupeň, do každého dalšího vrcholu vede právě jedna hrana (má tedy vstupní stupeň ) a všechny vrcholy jsou z kořene orientovaně dostupné. V kořenových stromech se užívá pro vrcholy přirozeným způsobem definovaných pojmů otec nebo rodič, synnebo dítě, předek, potomek. List v kořenovém stromu je vrchol výstupního stupně, který tedy již nemá žádné syny. Kořenový strom se dá kreslit velmi názorně. 4
.3 Reprezentace grafů Obecný popis grafu, bez ohledu na prostředek, který je použit, musí popisovat pisovat množinu vrcholů V, množinu hran H a incidenční zobrazení f. Jedině takovým popisem je graf zadán úplně. Nejčastěji se setkáme s popisem grafu pomocí matic, nebo pomocí seznamů, které jsou vhodnější pro počítačové čové zpracování..3. Matice sousednosti Matice sousednosti je velmi jednoduchá a intuitivní. V řádcích i ve sloupcích budou uzly. Číslo na dané pozici v matici bude znamenat, že příslušné uzly spolu sousedí, jinak na této pozici bude číslo. Pro neorientovaný graf bude matice symetrická a vystačili bychom tedy jen s trojúhelníkovou maticí..3.2 Matice incidencee Jiným prostředkem, jak graf popsat psat maticí, je tak zvaná matice incidence ce uzlů a hran. Užívá se u grafů bez smyček. Konstrukce této matice vyžaduje stanovit jisté pořadí uzlů a hran. Má-li graf n vrcholů a m hran, je to obdélníková matice typu (m,n). Řádky odpovídajíí vrcholům, sloupce hranám grafu. U orientovaných grafů je v i-tém sloupci a j-tém řádku číslo, pokud je i-tý vrchol počátečním vrcholem j-té hrany, a číslo -, pokud je jejím koncovým vrcholem. Ostatní prvky matice jsou nuly. Incidenční matice orientovaného grafu bez smyček má v každém sloupci vždy jednu hodnotu a jednu hodnotu -. Ostatní jsou nuly. U neorientovaných grafů je na místě i,j jednička, pokud je i-tý vrch hol incidentní s j-tou hranou, a nula jindy. U neorientovaných grafů jsou v každém sloupci právě dvě jedničky. Příklad: Pro následující orientovaný a neorientovaný graf sestrojte matice incidence a matice sousednosti. Řešení: Incidenční matice uzlů a hran: h - E h2 h3 - - h4 h5 h6 h7 - - - - h h2 E h3 h4 h5 h6 h7 Matice sousednosti: E E 5
E E.3.3 Matice dostupnosti Vrchol y orientovaného grafu G dostupný z vrcholu x právě když v grafu existuje orientovaná cesta z x do y. Jsou-li vrcholy grafu G uspořádány do posloupnosti u, u 2,, u n, pak můžeme vytvořit matici = (d i,j ) dostupnosti uzlů, která je následujícím předpisem pro její prvky d i,j : d i,j =, jestliže uzel u j je dostupný z uzlu u i d i,j =, v ostatních případech lgoritmus pro získání matice dostupnosti:. inicializace: Označkujeme vrchol v, ostatní značku nemají 2. test ukončení: Je-li množina neoznačkovaných vrcholů rázdná, algoritmus končí 3. volba hrany: Zvolíme libovolně hranu h, jejíž očáteční vrchol je označkován a koncový vrchol v označkovánn není 4. značkování: označkujeme vrchol v a pokračujeme bodem 2 Příklad: Pro následující orientovaný graf sestrojte matici dostupnosti. Řešení: E E.3.4 Matice vzdáleností Jsou-li vrcholy grafu očíslovány, pak vzdálenosti u(i,j) s indexy i a j tvoří tzv. matici vzdáleností. Tuto matici lze vypočítat tak, že opakovaným použitím kteréhokoliv algoritmu pro výpočet nejkratších cest najdeme postupně nejkratší cestu a tím I vzdálenost z každého vrcholu do každého vrcholu. Místo tohoto nepraktického přístupu si později ukážeme jednoduchý, rychlý a elegantní postup, který je znám jako Floydův algoritmus. 6
.3.5 Seznam sousednosti Pro každý vrchol je vytvořen seznam sousedů. Sousedící vrcholy jsou obecně uloženy v seznamech v libovolném pořadí. Vlevo je příklad neorientovaného grafu, vpravo příklad orientovaného grafu: Tyto dva grafy budeme reprezentovat seznamem sousednosti takto:.3.6 Seznam uzlů pro kořenové stromy Zvláštní postavení mezi grafy mají orientované kořenové stromy. Jejich použití je velmi časté. Pro kořenové stromy se používají speciálně zřetězené seznamy tvaru: u : p, q; u 2 : p, q ;... ; u n : p, q; u -O: p, q; u 2 -O: p, q ;... ; u n -O: p, q; Je-li u i otec, potom p je ukazatel na jeho nejstaršího (nejlevějšího) potomka, q je ukazatel na nejstaršího z mladších sourozenců. Orientace jde směrem dolů, tedy jsou definovány orientované hrany z uzlu u i na uzly zadané ukazateli p,q. U binárního stromu je výhodné chápat ukazatel q jako ukazatel na pravého potomka. Každému uzlu náleží jeden prvek spojového seznamu. Pokud jde o ohodnocení uzlů, tak se u každého uzlu uvádí do jemu náležícího prvku spojového seznamu (např. za ukazatele). Spojový seznam, uvedený níže, prezentuje následující kořenový graf: 7
.3.7 Reprezentace stromů v tabulce Pro reprezentaci struktury v SQL se používá zpravidla jedna tabulka, ve které si ukládáme identifikaci rodičovského uzlu a identifikátor uzlu. Je-li potřeba vytvořit strom s více rodiči pro jeden uzel, tabulka se rozdělí na dvě. Jedna tabulka bude obsahovat seznam uzlů a ve druhé budou zaznamenány vazeb mezi uzly (tzv. vztah uzlů M:N). V případě binárního stromu se používá tabulka se třemi sloupci kde je zaznamenána hodnota, levý a pravý ukazatel na potomka. Příklad: Následující strom zapište ve forme SQL tabulky. Řešení: id uzlu E F G H I id_rodiče F F I G.4 Optimalizační úlohy nad grafy V této kapitole popíšeme několikk vybraných optimalizačních úloh na grafech. yly vybrány úlohy, které se často vyskytují při řešení ekonomických, plánovacích či organizačních problémů a na kterých bude možné ukázat, jak lze užít základní principy návrhu efektivních algoritmů v konkrétních situacích..4. Prohledávání grafu do hloubky Tento algoritmus je též někdy označován zkratkou FS (epth First Search). Vstup: Vstupem algoritmu je libovolný orientovaný nebo neorientovaný souvislý graf. 8
Inicializace: Na začátku algoritmu uložíme do zásobníku startovací uzel (vrchol grafu, ve kterém zahajujeme prohledávání). Popis: Z uzlu, který je na vrcholu zásobníku, se vydáme po hraně do některého z jeho neoznačených následníků. Každý takovýto neoznačený uzel, do kterého vede hrana, přidáme na zásobník a opět se vydáme po hraně do některého z jeho neoznačených následníků, který přidáme na vrchol zásobníku. Takto postupujeme, dokud nenarazíme na uzel, který žádné další neoznačené následníky nemá. Tento uzel vyjmeme z vrcholu zásobníku, označíme (nastavíme mu příznak) a ukončíme jeho prohledávání. V prohledávání se vrátíme do uzlu, který je momentálně na vrcholu zásobníku a celý proces opakujeme, dokud zásobník není prázdný. Výstup: Prohledané uzly grafu je možné zachytit tzv. preorder, tedy v pořadí, v jakém byly ukládány na zásobník, nebo postorder, tedy v pořadí, v jakém bylo ukončeno jejich prohledávání. Následující obrázek ilustruje, jak algoritmus prohledávání grafu do hloubky prochází grafem:.4.2 Prohledávání grafu do šířky Jde o grafový algoritmus, který postupně prochází všechny vrcholy daného souvislého grafu. lgoritmus nejprve projde všechny následníky startovního vrcholu, poté následníky následníků a tak dál až projde celý souvislý graf. Při zpracovávání uzlu řadíme všechny jeho následníky do fronty (FIFO) a zpracováváme vždy první uzel z fronty. Vstup: Vstupem algoritmu je libovolný orientovaný nebo neorientovaný souvislý graf. Inicializace: Na začátku algoritmu uložíme do frontystartovací uzel (vrchol grafu, ve kterém zahajujeme prohledávání). Popis: Vybereme vrchol, který je na začátku fronty a na konec fronty přidáme všechny jeho přímé následníky, do kterých vede z tohoto vrcholu hrana a u nichž ještě nebylo ukončeno prohledávání (které zatím neprošly frontou). Prohledávání tohoto vrcholu poté ukončíme. Opět vybereme vrchol na počátku fronty a celý postup opakujeme. Nemá-li některý z vrcholů žádné následníky, rovnou ukončíme jeho prohledávání a přejdeme k vrcholu na začátku fronty. lgoritmus končí, jakmile je fronta prázdná a nemáme dál co prohledávat. Výstup: Výstupem algoritmu je pořadí uzlů v jakém byly ukládány do fronty (pořadí, v jakém bylo ukončeno jejich prohledávání). Následující obrázek ilustruje, jak algoritmus prohledávání grafu do šířky prochází grafem: 9
..4.3 ijkstrův algoritmus ijkstrův algoritmus řeší problém nejkratších cest z kořene s (startovací vrchol, ze kterého začínáme) do ostatních vrcholů grafu pro grafy s nezáporným ohodnocením hran. Označíme si výchozí uzel, ze kterého budeme plánovat cestu. ijsktrův algoritmus je založen na tom, že na začátku přiřadíme uzlům určité hodnoty a postupně jej budeme vylepšovat. lgoritmus si popíšeme ve slovním pseudokódu:. Ke každému uzlu přiřaď aktuální vzdálenost od počátečního uzlu. V případě samotného výchozího uzlu je vzdálenost, v případě ostatních uzlů je to nyní nekonečno. 2. Označ všechny uzly jako nenavštívené. Označ výchozí uzel jako aktuální uzel. Vytvoř množinu nenavštívených uzlů, která bude obsahovat všechny uzly kromě výchozího. Nyní se dostáváme k třetímu bodu, který se bude opakovat ve smyčce. 3. Podívej se na všechny nenavštívené sousedy aktuálního uzluu a vypočítej jejich vzdálenost od počátečního uzlu. Pokud má např. aktuální uzel vzdálenost 3 a délka hrany mezi tímto uzlem a jeho sousedem je 2, potom vzdálenost k omuto sousedovi bude 3 + 2 = 5. Pokud je aktuální vzdálenost menší než dříve zaznamenaná vzdálenost tohotoo souseda, pak ji přepiš lepší, kratší hodnotou. Poznamenejme, že i když jsme se na sousední uzly aktuálního uzlu podívali, stále zůstávají v množině nenavštívených. 4. Jakmile jsme se podívali na sousedy aktuálního uzlu, budeme považovat tento aktuální uzel za navštívený a vyjmeme ho z množiny nenavštívených uzlů. K tomuto uzlu už se nikdy nevrátíme. 5. Pokud byla cílová destinace označenaa jako navštívená, nebo nejmenší aktuální vzdálenost mezi uzly v množině nenavštívených uzlů je nekonečno, ukonči algoritmus. 6. Vyber uzel z množiny nenavštívených uzlů, který má nejmenší aktuální vzdálenost od výchozího uzlu, nastav jej jako aktuální uzel a vrať se k bodu 3. Pokud Vám pseudokód připomíná algoritmus procházení do šířky, není tomu tak náhodou. ijsktrův algoritmus je skutečně rozšířením procházení grafu do šířky, přičemž místo datové struktury fronta zde využíváme podobnéhoo nástroje, kterým je prioritní fronta. Prioritní fronta funguje jako fronta, ve které mohou předbíhat uzly s nejkratší aktuální vzdáleností od zdroje. lgoritmus tedy systematicky postupuje od výchozího uzlu k cílové destinaci a aktualizuje vzdálenosti. Výstupem algoritmu je pak délka nejkratší cesty z výchozího uzlu do všech ostatních uzlů. Příklad: Vyhledejtee nejkratší cestu z počátečního uzlu do všech ostatních uzlů ohodnoceného grafu.
Řešení: použijeme ijkstrův algoritmus: E F množina X, 3, 4, max max - 8, - 4,, max, - 8, - -,,,, - - - -,,,,, - - - - -,,,,,E - - - - -,,,,E Výsledek tedy bude: E F 8, 3, 4,,,.4.3 Floydův algoritmus Floydův algoritmus slouží především k vyhledání vzdáleností (vzdálenost = délka minimální cesty) v ohodnocených grafech. lgoritmus je založen na porovnání hodnot přímých a nepřímých vzdáleností. Využíváme toho, že hrana (i,j) patří do minimální cesty tehdy, pokud nevede minimální cesta jinudy. Zapsáno matematicky: ( i, j) + o( i, j) < d( r j) d, Floydův algoritmus je tvořen z následujícími kroky:. Sestavení matice přímých vzdáleností, přičemž pro prvky c ij této matice platí: c = pokud i = j, ij ( i j) c ij = o, pokud i j a hrana spojující uzly j c = pokud i j a hrana spojující uzly j ij i, existuje, i, neexistuje. 2. Zavedeme pomocnou proměnnou k a položíme k =. Tato proměnná představuje index vrcholu, pře který provádíme přepočet. 3. Provedeme přepočet jednotlivých prvků c ij matice podle pravidla ij { c c c } c = mni, +, přičemž nepropočítáváme prvky matice, pro které platí i = j ij ik kj (hlavní diagonála matice), prvky, pro které platí i, j = k (leží v řádku či sloupci s indexem k), a prvky i k a j k, pro které c = a c =. 4. Pokud n kroku 3). Je li vzdáleností. ik k < (n je počet vrcholů grafu), potom položíme = k + k = n kj k a vracíme se zpět ke, je výpočet ukončen a poslední získaná matice je hledanou maticí Příklad: V zadaném grafu nalezněte vzdálenosti mezi jednotlivými vrcholy pomocí Floydova algoritmu.
Řešení: 3 3 2 4 7 K= 3 3 2 4 7 K=2 3 3 2 4 7 9 K=3 3 3 2 7 6 4 7 9.5 Literatura Pro další studium problematiky grafů doporučuji čtenáři následující literaturu: Šišma P. (997): Teorie grafů 736-963, Prometheus, Praha Vaníček J. a kolektiv (28): Teoretické základy informatiky, Kernberg Publishing, s.r.o., Praha Jirovský L. (2): Teorie grafů ve výuce na střední škole, diplomová práce, MFF UK, Praha Renc Z. (2): Sbírka řešených úloh z matematiky, fyziky a informatiky (přijímací řízení na MFF UK v letech 992-999), matfyz press, Praha Hliněný P. (22): Matematické Základy Informatiky, skripta FI MU rno 2