Topologické uspořádání (TU) orientovaného grafu $G = (V, E)$ je takové seřazení vrcholů $V = {v_1, . . . , v_n}$, že pro každou orientovanou hranu $(v_i , v_j ) \in E$ platí $\boldsymbol{i} \boldsymbol{<} \boldsymbol{j}$.
Jinými slovy, pokud vrcholy zakreslíme horizontálně v pořadí topologického uspořádání, budou všechny orientované hrany směřovat zleva doprava.
Topologické uspořádání se používá především pro plánování pořadí provedení navzájem závislých úloh/výpočtů.
Pokud graf obsahuje cyklus, nelze tuto úlohu zjevně vyřešit
TopSort
Existence zdroje v orientovaném acyklickém grafu vede přímočaře na algoritmus konstrukce topologického uspořádání takového grafu.
Vstup: Orientovaný graf $G$.
Výstup: Nějaké topologické uspořádání $G$, pokud byl acyklický, a detekce cykličnosti v opačném případě.
Idea:
Průběžně počítej vstupní stupně vrcholů (tj. počet hran, ve kterých je vrchol následníkem)
Zdroje zařazuj do fronty,
Odebírej vrcholy z fronty, zařazuj je do výstupního pořadí a odebírej je z grafu a to znamená, že jejich následníkům snižuj vstupní stupně.
Pokud po vyprázdnění fronty zbyly v grafu nějaké vrcholy, byl v něm orientovaný cyklus.
Algoritmus 5.3: TopSort
TopSort)
Algoritmus TopSort ($G$) spuštěný na orientovaný graf $G$ doběhne v konečném čase a buď vygeneruje korektní topologické uspořádání
acyklického grafu nebo detekuje existenci orientovaného cyklu.
Předpokládejme, že G je orientovaný graf a předpokládejme, že na počátku v kroku (7) existuje aspoň jeden zdroj $z$ a že všechny zdroje zařadíme do fronty $Q$.
Vnitřek cyklu (8)-(17) realizuje odebrání 1 zdroje z fronty Q, jeho vyjmutí z grafu G, jeho vložení do výsledného uspořádání a identifikaci případných nových zdrojů a jejich zařazení do Q.
Existence hrany $(v_i , v_j)$ znemožňuje vložit vrchol $v_j$ do fronty $Q$ před vrcholem $v_i$, protože $v_j$ by v takovém okamžiku mělo $\delta[v_j] \gt 1$ a podmínkou vložení do $Q$ je $\delta[v_j] = 0$.
Pokud v okamžiku vyprázdnění fronty jsou zpracovány všechny vrcholy grafu $G$, našli jsme TU orientovaného acyklického grafu.
Pokud je fronta prázdná a přesto zbývají nějaké nezpracované vrcholy ve zbytku $G$, pak ve zbytku $G$ nejsou žádné zdroje, čili každý vrchol má vstupní hranu/-y a musí existovat orientovaný cyklus, plus případně z něj dostupné podgrafy. Vrcholy tohoto zbytkového grafu nelze topologicky uspořádat
Algoritmus tedy správně detekuje existenci cyklu a skončí v konečném čase
V obou případech algoritmus pracuje korektně a zastaví se
$\square$
TopSort)
Algoritmus TopSort ($G$), kde $G = (V, E)$ je orientovaný graf reprezentovaný pomocí pole následníků, má časovou i paměťovou složitost $O(|V | + |E|)$.
Výpočet pole vstupních stupňů na řádcích (4)-(5) trvá $\Theta(|E|)$.
Počáteční vložení zdrojů do $Q$ na řádku (7) trvá $O(|V|)$.
Každý vrchol je vložen do $Q$ nejvýše 1x, proto vybírání z $Q$ a výpis na výstup na řádcích (9)–(10) trvá $O(|V|)$.
Každá hrana může být odebrána z grafu nejvýše 1x, proto operace na řádcích (11)–(16) trvají $O(|E|)$.
Celková časová složitost je tedy $O(|V| + |E|)$.
Graf $G$, pole $\delta[]$, fronta $Q$, to vše zabere $O(|V| + |E|)$ paměti.
$\square$
Jak vypadají orientované grafy s právě dvěma topologickými uspořádáními?
Jak vypadají orientované grafy s právě třemi topologickými uspořádáními?
Fungoval by algoritmus TopSort i s jinou strukturou než
frontou? Co třeba se zásobníkem?
Navrhněte, jak modifikovat algoritmus DFS pro orientované grafy, aby vytvořil TU grafu.