From: Martin Mares Date: Tue, 22 Nov 2016 13:59:56 +0000 (+0100) Subject: Překódování do UTF-8 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=1fdf44d6c4b891a7e3bfa6a46a79afe5acd88bb6;p=ga.git Překódování do UTF-8 --- diff --git a/0-intro/0-intro.tex b/0-intro/0-intro.tex index 908b594..c70a6c8 100644 --- a/0-intro/0-intro.tex +++ b/0-intro/0-intro.tex @@ -1,63 +1,63 @@ \input ../sgr.tex -\prednaska{0}{Úvodem}{} - -Tento spisek vznikl jako uèební text k~pøedná¹ce z~grafových algoritmù, -kterou pøedná¹ím na~Katedøe aplikované matematiky MFF UK v~Praze. Rozhodnì -si neklade za cíl dùkladnì zmapovat celé v~dne¹ní dobì ji¾ znaènì rozko¹atìlé odvìtví -informatiky zabývající se grafy, spí¹e se sna¾í ukázat nìkteré typické techniky -a teoretické výsledky, které se pøi návrhu grafových algoritmù pou¾ívají. -Zkrátka je to takový turistický prùvodce krajinou grafových algoritmù. - -Jeliko¾ pøedná¹ka se øadí mezi pokroèilé kursy, dovoluji si i v~tomto -textu pøedpokládat základní znalosti teorie grafù a grafových algoritmù. -V~pøípadì pochybností doporuèuji obrátit se na~nìkterou z~knih \cite{kapitoly}, -\cite{demel} a \cite{kucera}. Výbornou referenèní pøíruèkou, ze~které jsem èastokrát èerpal -i já pøi sestavování pøedná¹ek, je také Schrijverova monumentální monografie +\prednaska{0}{Úvodem}{} + +Tento spisek vznikl jako učební text k~přednášce z~grafových algoritmů, +kterou přednáším na~Katedře aplikované matematiky MFF UK v~Praze. Rozhodně +si neklade za cíl důkladně zmapovat celé v~dneÅ¡ní době již značně rozkoÅ¡atělé odvětví +informatiky zabývající se grafy, spíše se snaží ukázat některé typické techniky +a teoretické výsledky, které se při návrhu grafových algoritmů používají. +Zkrátka je to takový turistický průvodce krajinou grafových algoritmů. + +Jelikož přednáška se řadí mezi pokročilé kursy, dovoluji si i v~tomto +textu předpokládat základní znalosti teorie grafů a grafových algoritmů. +V~případě pochybností doporučuji obrátit se na~některou z~knih \cite{kapitoly}, +\cite{demel} a \cite{kucera}. Výbornou referenční příručkou, ze~které jsem častokrát čerpal +i já při sestavování přednášek, je také Schrijverova monumentální monografie Combinatorial Optimization~\cite{schrijver}. -Mé díky patøí studentùm Semináøe z~grafových algoritmù, na~kterém jsem -na~jaøe 2006 první verzi této pøedná¹ky uvádìl, za~výbornì zpracované -zápisky, je¾ se staly prazákladem tohoto textu. Jmenovitì: +Mé díky patří studentům Semináře z~grafových algoritmů, na~kterém jsem +na~jaře 2006 první verzi této přednášky uváděl, za~výborně zpracované +zápisky, jež se staly prazákladem tohoto textu. Jmenovitě: $$\vbox{\halign{\it #\hfil\cr -Toky, øezy a Fordùv-Fulkersonùv algoritmus: Radovan ©esták \cr -Dinicùv algoritmus: Bernard Lidický \cr -Globální souvislost a párování: Jiøí Peinlich a Michal Kùrka \cr +Toky, řezy a Fordův-Fulkersonův algoritmus: Radovan Å esták \cr +Dinicův algoritmus: Bernard Lidický \cr +Globální souvislost a párování: Jiří Peinlich a Michal Kůrka \cr Gomory-Hu Trees: Milan Straka \cr -Minimální kostry: Martin Kruli¹, Petr Su¹il, Petr ©koda a Tomá¹ Gavenèiak \cr -Poèítání na RAMu: Zdenìk Vilu¹ínský \cr +Minimální kostry: Martin KruliÅ¡, Petr SuÅ¡il, Petr Å koda a Tomáš Gavenčiak \cr +Počítání na RAMu: Zdeněk Vilušínský \cr Q-Heapy: Cyril Strejc \cr -Suffixové stromy: Tomá¹ Mikula a Jan Král \cr -Dekompozice Union-Findu: Ale¹ ©nupárek \cr +Suffixové stromy: Tomáš Mikula a Jan Král \cr +Dekompozice Union-Findu: AleÅ¡ Å nupárek \cr }}$$ -Dìkuji také tvùrcùm vektorového editoru Vrr, v~nìm¾ jsem kreslil vìt¹inu obrázkù. +Děkuji také tvůrcům vektorového editoru Vrr, v~němž jsem kreslil větÅ¡inu obrázků. \medskip -\>V~Praze v~bøeznu 2007 +\>V~Praze v~březnu 2007 -\rightline{Martin Mare¹\qquad\qquad} +\rightline{Martin MareÅ¡\qquad\qquad} \bigskip -\h{Znaèení} +\h{Značení} -\>V~celém textu se budeme dr¾et tohoto základního znaèení: +\>V~celém textu se budeme držet tohoto základního značení: \itemize\ibull -\:$G$ bude znaèit koneèný {\I graf} na~vstupu algoritmu (podle potøeby buïto orientovaný - nebo neorientovaný; multigraf jen bude-li explicitnì øeèeno). -\:$V$ a $E$ budou mno¾iny {\I vrcholù} a {\I hran} grafu~$G$ (pøípadnì jiného grafu - uvedeného v~závorkách). Hranu z~vrcholu~$u$ - do~vrcholu~$v$ budeme psát~$uv$, a» u¾ je orientovaná nebo~ne. -\:$n$ a $m$ bude {\I poèet vrcholù a hran,} tedy $n:=\vert V\vert$, $m:=\vert E\vert$. -\:Pro libovolnou mno¾inu $X$ vrcholù nebo hran bude $\overline X$ oznaèovat doplnìk - této mno¾iny; pøitom z~kontextu by mìlo být v¾dy jasné, vzhledem k~èemu. +\:$G$ bude značit konečný {\I graf} na~vstupu algoritmu (podle potřeby buďto orientovaný + nebo neorientovaný; multigraf jen bude-li explicitně řečeno). +\:$V$ a $E$ budou množiny {\I vrcholů} a {\I hran} grafu~$G$ (případně jiného grafu + uvedeného v~závorkách). Hranu z~vrcholu~$u$ + do~vrcholu~$v$ budeme psát~$uv$, aÅ¥ už je orientovaná nebo~ne. +\:$n$ a $m$ bude {\I počet vrcholů a hran,} tedy $n:=\vert V\vert$, $m:=\vert E\vert$. +\:Pro libovolnou množinu $X$ vrcholů nebo hran bude $\overline X$ označovat doplněk + této množiny; přitom z~kontextu by mělo být vždy jasné, vzhledem k~čemu. \endlist -\>Také budeme bez újmy na~obecnosti pøedpokládat, ¾e zpracovávaný graf je souvislý -Èasovou slo¾itost prùchodu grafem do~hloubky èi ¹íøky pak mù¾eme psát jako $\O(m)$, -proto¾e víme, ¾e $n=\O(m)$. +\>Také budeme bez újmy na~obecnosti předpokládat, že zpracovávaný graf je souvislý +Časovou složitost průchodu grafem do~hloubky či šířky pak můžeme psát jako $\O(m)$, +protože víme, že $n=\O(m)$. \references \bye diff --git a/1-toky/1-toky.tex b/1-toky/1-toky.tex index 797c7b0..03f3ae1 100644 --- a/1-toky/1-toky.tex +++ b/1-toky/1-toky.tex @@ -1,262 +1,262 @@ \input ../sgr.tex -\prednaska{1}{Toky, øezy a Fordùv-Fulkersonùv algoritmus}{} +\prednaska{1}{Toky, řezy a Fordův-Fulkersonův algoritmus}{} -V~této kapitole nadefinujeme toky v~sítích, odvodíme základní vìty o~nich -a také Fordùv-Fulkersonùv algoritmus pro hledání maximálního toku. Také uká¾eme, -jak na~hledání maximálního toku pøevést problémy týkající se øezù, separátorù -a párování v~bipartitních grafech. Dal¹í tokové algoritmy budou následovat v~pøí¹tích kapitolách. +V~této kapitole nadefinujeme toky v~sítích, odvodíme základní věty o~nich +a také Fordův-Fulkersonův algoritmus pro hledání maximálního toku. Také ukážeme, +jak na~hledání maximálního toku převést problémy týkající se řezů, separátorů +a párování v~bipartitních grafech. Další tokové algoritmy budou následovat v~příštích kapitolách. -\h{Toky v sítích} +\h{Toky v sítích} -Intuitivní pohled: sí» je systém propojených potrubí, který pøepravuje tekutinu -ze~zdroje~$s$ (source) do~spotøebièe~$t$ (target), pøièem¾ tekutina -se nikde mimo tato dvì místa neztrácí ani nevzniká. +Intuitivní pohled: síť je systém propojených potrubí, který přepravuje tekutinu +ze~zdroje~$s$ (source) do~spotřebiče~$t$ (target), přičemž tekutina +se nikde mimo tato dvě místa neztrácí ani nevzniká. \ss{Definice:} \itemize\ibull -\:{\I Sí»} je uspoøádaná pìtice $(V,E,s,t,c)$, kde: +\:{\I Síť} je uspořádaná pětice $(V,E,s,t,c)$, kde: \itemize\ibull - \:$(V,E)$ je orientovaný graf, + \:$(V,E)$ je orientovaný graf, \:$s\in V$ {\I zdroj,} - \:$t\in V$ {\I spotøebiè} neboli {\I stok} a - \:$c: E\rightarrow {\bb R}$ funkce udávající nezáporné {\I kapacity} hran. + \:$t\in V$ {\I spotřebič} neboli {\I stok} a + \:$c: E\rightarrow {\bb R}$ funkce udávající nezáporné {\I kapacity} hran. \endlist -\:{\I Ohodnocení} hran je libovolná funkce $f:\, E\rightarrow {\bb R}$. Pro ka¾dé ohodnocení $f$ - mù¾eme definovat: +\:{\I Ohodnocení} hran je libovolná funkce $f:\, E\rightarrow {\bb R}$. Pro každé ohodnocení $f$ + můžeme definovat: $$ f^+(v) = \sum_{e=(\cdot,v)} f(e), \quad f^-(v) = \sum_{e=(v,\cdot)} f(e), \quad f^\Delta(v) = f^+(v) - f^-(v) $$ - [co do~vrcholu pøiteèe, co odteèe a jaký je v~nìm pøebytek]. -\:{\I Tok} je ohodnocení $f:\, E\rightarrow {\bb R}$, pro které platí: + [co do~vrcholu přiteče, co odteče a jaký je v~něm přebytek]. +\:{\I Tok} je ohodnocení $f:\, E\rightarrow {\bb R}$, pro které platí: \itemize\ibull - \:$\forall e: 0 \le f(e) \le c(e)$, \quad {\I (dodr¾uje kapacity)} - \:$\forall v\ne s,t: f^\Delta(v)=0$. \quad {\I (Kirchhoffùv zákon)} + \:$\forall e: 0 \le f(e) \le c(e)$, \quad {\I (dodržuje kapacity)} + \:$\forall v\ne s,t: f^\Delta(v)=0$. \quad {\I (Kirchhoffův zákon)} \endlist \:{\I Velikost toku:} $\vert f \vert = -f^\Delta(s)$. -\:{\I Øez (tokový):} mno¾ina vrcholù $C\subset V$ taková, ¾e $s\in C$, $t\not\in C$. Øez mù¾eme také - ztoto¾nit s~mno¾inami hran $C^- = E \cap (C \times \overline C)$ [tìm budeme øíkat hrany zleva doprava] +\:{\I Řez (tokový):} množina vrcholů $C\subset V$ taková, že $s\in C$, $t\not\in C$. Řez můžeme také + ztotožnit s~množinami hran $C^- = E \cap (C \times \overline C)$ [těm budeme říkat hrany zleva doprava] a $C^+ = E \cap (\overline C \times C)$ [hrany zprava doleva]. -\:{\I Kapacita øezu:} $\vert C \vert = \sum_{e \in C^-} c(e)$ (bereme v~úvahu jen hrany zleva doprava). -\:{\I Tok pøes øez:} +\:{\I Kapacita řezu:} $\vert C \vert = \sum_{e \in C^-} c(e)$ (bereme v~úvahu jen hrany zleva doprava). +\:{\I Tok přes řez:} $f^+(C)=\sum_{e\in C^+} f(e)$, $f^-(C)=\sum_{e \in C^-} f(e)$, $f^\Delta(C)=f^+(C)-f^-(C)$. -\:{\I Cirkulace} je tok nulové velikosti, èili $f$ takové, ¾e $f^\Delta(v)=0$ pro v¹echna~$v$. +\:{\I Cirkulace} je tok nulové velikosti, čili $f$ takové, že $f^\Delta(v)=0$ pro vÅ¡echna~$v$. \endlist -Základním problémem, kterým se budeme zabývat, je hledání {\I maximálního toku} (tedy toku nejvìt¹í mo¾né -velikosti) a {\I minimálního øezu} (øezu nejmen¹í mo¾né kapacity). +Základním problémem, kterým se budeme zabývat, je hledání {\I maximálního toku} (tedy toku největší možné +velikosti) a {\I minimálního řezu} (řezu nejmenší možné kapacity). \goodbreak -\s{Vìtièka:} V~ka¾dé síti existuje maximální tok a minimální øez. +\s{Větička:} V~každé síti existuje maximální tok a minimální řez. -\proof Existence minimálního øezu je triviální, proto¾e øezù v~ka¾dé síti je koneènì mnoho; -pro toky v~sítích s~reálnými kapacitami to ov¹em není samozøejmost a je k~tomu potøeba trocha matematické -analýzy (v~prostoru v¹ech ohodnocení hran tvoøí toky kompaktní mno¾inu, velikost toku je lineární funkce, -a~tedy i spojitá, proèe¾ nabývá maxima). Pro racionální kapacity dostaneme tuto vìtièku jako dùsledek -analýzy Fordova-Fulkersonova algoritmu. +\proof Existence minimálního řezu je triviální, protože řezů v~každé síti je konečně mnoho; +pro toky v~sítích s~reálnými kapacitami to ovÅ¡em není samozřejmost a je k~tomu potřeba trocha matematické +analýzy (v~prostoru vÅ¡ech ohodnocení hran tvoří toky kompaktní množinu, velikost toku je lineární funkce, +a~tedy i spojitá, pročež nabývá maxima). Pro racionální kapacity dostaneme tuto větičku jako důsledek +analýzy Fordova-Fulkersonova algoritmu. \qed -\s{Pozorování:} Kdybychom velikost toku definovali podle spotøebièe, vy¹lo by toté¾. Platí toti¾: +\s{Pozorování:} Kdybychom velikost toku definovali podle spotřebiče, vyÅ¡lo by totéž. Platí totiž: $$f^\Delta(s) + f^\Delta(t) = \sum_v f^\Delta(v) = \sum_e f(e) - f(e) = 0$$ -(první rovnost plyne z~Kirchhoffova zákona -- v¹echna ostatní $f^\Delta(v)$ jsou nulová; druhá pak z~toho, -¾e ka¾dá hrana pøispìje k~jednomu $f^+(v)$ a k~jednomu $f^-(v)$). Proto je $\vert f\vert = -f^\Delta(s) = f^\Delta(t).$ +(první rovnost plyne z~Kirchhoffova zákona -- vÅ¡echna ostatní $f^\Delta(v)$ jsou nulová; druhá pak z~toho, +že každá hrana přispěje k~jednomu $f^+(v)$ a k~jednomu $f^-(v)$). Proto je $\vert f\vert = -f^\Delta(s) = f^\Delta(t).$ -Stejnì tak mù¾eme velikost toku zmìøit na~libovolném øezu: +Stejně tak můžeme velikost toku změřit na~libovolném řezu: -\s{Lemma:} Pro ka¾dý øez $C$ platí, ¾e $\vert f\vert = -f^\Delta(C) \le \vert C \vert$. +\s{Lemma:} Pro každý řez $C$ platí, že $\vert f\vert = -f^\Delta(C) \le \vert C \vert$. -\proof První èást indukcí: ka¾dý øez mù¾eme získat postupným pøidáváním vrcholù do~triviálního øezu $\{s\}$ -[èili pøesouváním vrcholù zprava doleva], a~to, jak uká¾e jednoduchý rozbor pøípadù, nezmìní $f^\Delta$. -Druhá èást: $-f^\Delta(C) = f^-(C) - f^+(C) \le f^-(C) \le \vert C \vert.$ \qed +\proof První část indukcí: každý řez můžeme získat postupným přidáváním vrcholů do~triviálního řezu $\{s\}$ +[čili přesouváním vrcholů zprava doleva], a~to, jak ukáže jednoduchý rozbor případů, nezmění $f^\Delta$. +Druhá část: $-f^\Delta(C) = f^-(C) - f^+(C) \le f^-(C) \le \vert C \vert.$ \qed -Víme tedy, ¾e velikost ka¾dého toku lze omezit kapacitou libovolného øezu. Kdybychom na¹li tok a øez stejné -velikosti, mù¾eme si proto být jisti, ¾e tok je maximální a øez minimální. To se nám opravdu povede, platí toti¾ -následující vìta: +Víme tedy, že velikost každého toku lze omezit kapacitou libovolného řezu. Kdybychom naÅ¡li tok a řez stejné +velikosti, můžeme si proto být jisti, že tok je maximální a řez minimální. To se nám opravdu povede, platí totiž +následující věta: -\s{Vìta (Ford, Fulkerson):} V~ka¾dé síti je velikost maximálního toku rovna velikosti minimálního øezu. +\s{Věta (Ford, Fulkerson):} V~každé síti je velikost maximálního toku rovna velikosti minimálního řezu. -\proof Jednu nerovnost jsme dokázali v~pøedchozím lemmatu, druhá plyne z~duality lineárního -programování [max. tok a min. øez jsou navzájem duální úlohy], ale k~pìknému kombinatorickému -dùkazu pùjde opìt pou¾ít Fordùv-Fulkersonùv algoritmus. +\proof Jednu nerovnost jsme dokázali v~předchozím lemmatu, druhá plyne z~duality lineárního +programování [max. tok a min. řez jsou navzájem duální úlohy], ale k~pěknému kombinatorickému +důkazu půjde opět použít Fordův-Fulkersonův algoritmus. \qed -\h{Fordùv-Fulkersonùv algoritmus} +\h{Fordův-Fulkersonův algoritmus} -Nejpøímoèaøej¹í zpùsob, jak bychom mohli hledat toky v~sítích, je zaèít s~nìjakým tokem (nulový je po~ruce v¾dy) -a postupnì ho zlep¹ovat tak, ¾e nalezneme nìjakou nenasycenou cestu a po¹leme po~ní \uv{co pùjde}. -To~bohu¾el nefunguje, ale mù¾eme tento postup trochu zobecnit a být ochotni pou¾ívat nejen hrany, -pro~které je $f(e) < c(e)$, ale také hrany, po~kterých nìco teèe v~protismìru a my mù¾eme tok -v~na¹em smìru simulovat odeètením od~toku v~protismìru. Trochu formálnìji: +Nejpřímočařejší způsob, jak bychom mohli hledat toky v~sítích, je začít s~nějakým tokem (nulový je po~ruce vždy) +a postupně ho zlepÅ¡ovat tak, že nalezneme nějakou nenasycenou cestu a poÅ¡leme po~ní \uv{co půjde}. +To~bohužel nefunguje, ale můžeme tento postup trochu zobecnit a být ochotni používat nejen hrany, +pro~které je $f(e) < c(e)$, ale také hrany, po~kterých něco teče v~protisměru a my můžeme tok +v~naÅ¡em směru simulovat odečtením od~toku v~protisměru. Trochu formálněji: \ss{Definice:} \itemize\ibull -\:{\I Rezerva} hrany $e=(v,w)$ pøi toku~$f$ se definuje jako $r(e) = (c(e) - f(e)) + f(e^\prime)$, kde $e^\prime=(w,v)$. - Pro úèely tohoto algoritmu budeme pøedpokládat, ¾e ke~ka¾dé hranì existuje hrana opaèná; pokud ne, dodefinujeme - si ji a dáme jí nulovou kapacitu. -\:{\I Zlep¹ující cesta} je orientovaná cesta, její¾ v¹echny hrany mají nenulovou rezervu. +\:{\I Rezerva} hrany $e=(v,w)$ při toku~$f$ se definuje jako $r(e) = (c(e) - f(e)) + f(e^\prime)$, kde $e^\prime=(w,v)$. + Pro účely tohoto algoritmu budeme předpokládat, že ke~každé hraně existuje hrana opačná; pokud ne, dodefinujeme + si ji a dáme jí nulovou kapacitu. +\:{\I ZlepÅ¡ující cesta} je orientovaná cesta, jejíž vÅ¡echny hrany mají nenulovou rezervu. \endlist \ss{Algoritmus:} \algo -\:$f \leftarrow \$. -\:Dokud existuje zlep¹ující cesta $P$ z~$s$ do~$t$: +\:$f \leftarrow \$. +\:Dokud existuje zlepÅ¡ující cesta $P$ z~$s$ do~$t$: \::$\varepsilon \leftarrow \min_{e\in P} r(e)$. -\::Zvìt¹íme tok $f$ podél~$P$ o~$\varepsilon$ (ka¾dé hranì $e\in P$ zvìt¹íme $f(e)$, pøípadnì zmen¹íme $f(e^\prime)$, podle toho, co jde). +\::Zvětšíme tok $f$ podél~$P$ o~$\varepsilon$ (každé hraně $e\in P$ zvětšíme $f(e)$, případně zmenšíme $f(e^\prime)$, podle toho, co jde). \endalgo -\s{Analýza:} Nejdøíve si rozmysleme, ¾e pro celoèíselné kapacity algoritmus v¾dy dobìhne: v~ka¾dém kroku -stoupne velikost toku o~$\varepsilon \ge 1$, co¾ mù¾e nastat pouze koneènì-krát. Podobnì pro racionální kapacity: -pøenásobíme-li v¹echny kapacity jejich spoleèným jmenovatelem, dostaneme sí» s~celoèíselnými kapacitami, -na~které se bude algoritmus chovat identicky a jak ji¾ víme, skonèí. Pro~iracionální kapacity obecnì -dobìhnout nemusí, zkuste vymyslet protipøíklad. +\s{Analýza:} Nejdříve si rozmysleme, že pro celočíselné kapacity algoritmus vždy doběhne: v~každém kroku +stoupne velikost toku o~$\varepsilon \ge 1$, což může nastat pouze konečně-krát. Podobně pro racionální kapacity: +přenásobíme-li vÅ¡echny kapacity jejich společným jmenovatelem, dostaneme síť s~celočíselnými kapacitami, +na~které se bude algoritmus chovat identicky a jak již víme, skončí. Pro~iracionální kapacity obecně +doběhnout nemusí, zkuste vymyslet protipříklad. -Uva¾me nyní situaci po~zastavení algoritmu. Funkce~$f$ je urèitì tok, proto¾e jím byla po~celou dobu -bìhu algoritmu. Prozkoumejme teï mno¾inu $C$ vrcholù, do~nich¾ po~zastavení algoritmu vede zlep¹ující cesta ze~zdroje. -Jistì $s\in C$, $t\not\in C$, tak¾e tato mno¾ina je øez. Navíc pro ka¾dou hranu $e\in C^-$ musí -být $f(e)=c(e)$ a pro ka¾dou $e'\in C^+$ je $f(e')=0$, proto¾e jinak by rezerva hrany~$e$ nebyla -nulová. Tak¾e $f^-(C) = \vert C \vert$ a $f^+(C) = 0$, èili $\vert f\vert = \vert C \vert$. +Uvažme nyní situaci po~zastavení algoritmu. Funkce~$f$ je určitě tok, protože jím byla po~celou dobu +běhu algoritmu. Prozkoumejme teď množinu $C$ vrcholů, do~nichž po~zastavení algoritmu vede zlepÅ¡ující cesta ze~zdroje. +Jistě $s\in C$, $t\not\in C$, takže tato množina je řez. Navíc pro každou hranu $e\in C^-$ musí +být $f(e)=c(e)$ a pro každou $e'\in C^+$ je $f(e')=0$, protože jinak by rezerva hrany~$e$ nebyla +nulová. Takže $f^-(C) = \vert C \vert$ a $f^+(C) = 0$, čili $\vert f\vert = \vert C \vert$. -Na¹li jsme tedy k~toku, který algoritmus vydal, øez stejné velikosti, a~proto, jak u¾ víme, -je tok maximální a øez minimální. Tím jsme také dokázali Fordovu-Fulkersonovu vìtu\foot{Dokonce -jsme ji dokázali i pro reálné kapacity, proto¾e mù¾eme algoritmus spustit rovnou na maximální tok místo -nulového a on se ihned zastaví a vydá certifikující øez.} a existenci maximálního toku. Navíc algoritmus nikdy -nevytváøí z~celých èísel necelá, èím¾ získáme: +NaÅ¡li jsme tedy k~toku, který algoritmus vydal, řez stejné velikosti, a~proto, jak už víme, +je tok maximální a řez minimální. Tím jsme také dokázali Fordovu-Fulkersonovu větu\foot{Dokonce +jsme ji dokázali i pro reálné kapacity, protože můžeme algoritmus spustit rovnou na maximální tok místo +nulového a on se ihned zastaví a vydá certifikující řez.} a existenci maximálního toku. Navíc algoritmus nikdy +nevytváří z~celých čísel necelá, čímž získáme: -\s{Dùsledek:} Sí» s~celoèíselnými kapacitami má maximální tok, který je celoèíselný. +\s{Důsledek:} Síť s~celočíselnými kapacitami má maximální tok, který je celočíselný. -\s{Èasová slo¾itost} F-F algoritmu mù¾e být pro obecné sítì a ne¹ikovnou volbu zlep¹ujících -cest obludná, ale jak dokázali Edmonds s~Karpem, pokud budeme hledat cesty prohledáváním -do~¹íøky (co¾ je asi nejpøímoèaøej¹í implementace), pobì¾í v~èase $\O(m^2n)$. Pokud budou -v¹echny kapacity jednotkové, snadno nahlédneme, ¾e staèí $\O(nm)$. Edmondsùv a Karpùv -odhad nebudeme dokazovat, místo toho si v~pøí¹tí kapitole pøedvedeme efektivnìj¹í algoritmus. +\s{Časová složitost} F-F algoritmu může být pro obecné sítě a neÅ¡ikovnou volbu zlepÅ¡ujících +cest obludná, ale jak dokázali Edmonds s~Karpem, pokud budeme hledat cesty prohledáváním +do~šířky (což je asi nejpřímočařejší implementace), poběží v~čase $\O(m^2n)$. Pokud budou +vÅ¡echny kapacity jednotkové, snadno nahlédneme, že stačí $\O(nm)$. Edmondsův a Karpův +odhad nebudeme dokazovat, místo toho si v~příští kapitole předvedeme efektivnější algoritmus. -\h{Øezy, separátory a $k$-souvislost} +\h{Řezy, separátory a $k$-souvislost} -Teorie tokù nám rovnì¾ poslou¾í ke~zkoumání násobné souvislosti grafù. +Teorie toků nám rovněž poslouží ke~zkoumání násobné souvislosti grafů. -\s{Definice:} Pro ka¾dý neorientovaný graf $G$ a libovolné jeho vrcholy $s,t$ zavedeme: +\s{Definice:} Pro každý neorientovaný graf $G$ a libovolné jeho vrcholy $s,t$ zavedeme: \itemize\ibull -\:{\I $st$-øez} je mno¾ina hran $F$ taková, ¾e v~grafu $G-F$ jsou - vrcholy $s,t$ v~rùzných komponentách souvislosti. -\:{\I $st$-separátor} je mno¾ina vrcholù $W$ taková, ¾e $s,t\not\in W$ a v~grafu $G-W$ - jsou vrcholy $s,t$ v~rùzných komponentách souvislosti. -\:{\I Øez} je mno¾ina hran, která je $xy$-øezem pro nìjakou dvojici vrcholù $x,y$. -\:{\I Separátor} je mno¾ina vrcholù, která je $xy$-separátorem pro nìjakou dvojici vrcholù $x,y$. -\:$G$ je {\I hranovì $k$-souvislý,} pokud $\vert V\vert > k$ a v¹echny øezy v~$G$ - mají alespoò~$k$ hran. -\:$G$ je {\I vrcholovì $k$-souvislý,} pokud $\vert V\vert > k$ a v¹echny separátory v~$G$ - mají alespoò~$k$ vrcholù. +\:{\I $st$-řez} je množina hran $F$ taková, že v~grafu $G-F$ jsou + vrcholy $s,t$ v~různých komponentách souvislosti. +\:{\I $st$-separátor} je množina vrcholů $W$ taková, že $s,t\not\in W$ a v~grafu $G-W$ + jsou vrcholy $s,t$ v~různých komponentách souvislosti. +\:{\I Řez} je množina hran, která je $xy$-řezem pro nějakou dvojici vrcholů $x,y$. +\:{\I Separátor} je množina vrcholů, která je $xy$-separátorem pro nějakou dvojici vrcholů $x,y$. +\:$G$ je {\I hranově $k$-souvislý,} pokud $\vert V\vert > k$ a vÅ¡echny řezy v~$G$ + mají alespoň~$k$ hran. +\:$G$ je {\I vrcholově $k$-souvislý,} pokud $\vert V\vert > k$ a vÅ¡echny separátory v~$G$ + mají alespoň~$k$ vrcholů. \endlist -V¹imnìte si, ¾e nesouvislý graf má øez i separátor nulové velikosti, tak¾e vrcholová i hranová 1-souvislost -splývají s~obyèejnou souvislostí pro v¹echny grafy o~alespoò dvou vrcholech. Hranovì 2-souvislé -jsou právì (netriviální) grafy bez {\I mostù,} vrcholovì 2-souvislé jsou ty bez {\I artikulací.} - -Pro orientované grafy mù¾eme $st$-øezy a $st$-separátory definovat analogicky -(toti¾, ¾e po~odstranìní pøíslu¹né mno¾iny hran èi vrcholù neexistuje orientovaná -cesta z~$s$ do~$t$), globální øezy a separátory ani vícenásobná souvislost se obvykle -nedefinují. - -\s{Poznámka:} Minimální orientované $st$-øezy podle této definice a minimální tokové øezy -podle definice ze~zaèátku kapitoly splývají: ka¾dý tokový øez~$C$ odpovídá $st$-øezu stejné -velikosti tvoøenému hranami v~$C^-$; naopak pro~minimální $st$-øez musí být mno¾ina -vrcholù dosa¾itelných z~$s$ po~odebrání øezu z~grafu tokovým øezem, opìt stejné velikosti. -[Velikost mìøíme souètem kapacit hran.] Dává tedy rozumný smysl øíkat obojímu stejnì. -Podobnì se chovají i neorientované grafy, pokud do~\uv{tokového} øezu poèítáme -hrany v~obou smìrech. - -Analogií tokù je pak existence nìjakého poètu disjunktních cest (vrcholovì nebo hranovì) -mezi vrcholy~$s$ a~$t$. Analogií F-F~vìty pak budou známé Mengerovy vìty: - -\s{Vìta (Mengerova, lokální hranová orientovaná):} -Buï $G$ orientovaný graf a $s,t$ nìjaké jeho vrcholy. Pak je velikost minimálního -$st$-øezu rovna maximálnímu poètu hranovì disjunktních $st$-cest.\foot{orientovaných +VÅ¡imněte si, že nesouvislý graf má řez i separátor nulové velikosti, takže vrcholová i hranová 1-souvislost +splývají s~obyčejnou souvislostí pro vÅ¡echny grafy o~alespoň dvou vrcholech. Hranově 2-souvislé +jsou právě (netriviální) grafy bez {\I mostů,} vrcholově 2-souvislé jsou ty bez {\I artikulací.} + +Pro orientované grafy můžeme $st$-řezy a $st$-separátory definovat analogicky +(totiž, že po~odstranění přísluÅ¡né množiny hran či vrcholů neexistuje orientovaná +cesta z~$s$ do~$t$), globální řezy a separátory ani vícenásobná souvislost se obvykle +nedefinují. + +\s{Poznámka:} Minimální orientované $st$-řezy podle této definice a minimální tokové řezy +podle definice ze~začátku kapitoly splývají: každý tokový řez~$C$ odpovídá $st$-řezu stejné +velikosti tvořenému hranami v~$C^-$; naopak pro~minimální $st$-řez musí být množina +vrcholů dosažitelných z~$s$ po~odebrání řezu z~grafu tokovým řezem, opět stejné velikosti. +[Velikost měříme součtem kapacit hran.] Dává tedy rozumný smysl říkat obojímu stejně. +Podobně se chovají i neorientované grafy, pokud do~\uv{tokového} řezu počítáme +hrany v~obou směrech. + +Analogií toků je pak existence nějakého počtu disjunktních cest (vrcholově nebo hranově) +mezi vrcholy~$s$ a~$t$. Analogií F-F~věty pak budou známé Mengerovy věty: + +\s{Věta (Mengerova, lokální hranová orientovaná):} +Buď $G$ orientovaný graf a $s,t$ nějaké jeho vrcholy. Pak je velikost minimálního +$st$-řezu rovna maximálnímu počtu hranově disjunktních $st$-cest.\foot{orientovaných cest z~$s$ do~$t$} -\proof Z~grafu sestrojíme sí» tak, ¾e $s$~bude zdroj, $t$~spotøebiè a v¹em -hranám nastavíme kapacitu na~jednotku. Øezy v~této síti odpovídají øezùm v~pùvodním -grafu. Podobnì ka¾dý systém hranovì disjunktních $st$-cest odpovídá toku stejné -velikosti a naopak ke~ka¾dému celoèíselnému toku dovedeme najít systém disjunktních -cest (hladovì tok rozkládáme na~cesty a prùbì¾nì odstraòujeme cirkulace, které -objevíme). Pak pou¾ijeme F-F vìtu. +\proof Z~grafu sestrojíme síť tak, že $s$~bude zdroj, $t$~spotřebič a vÅ¡em +hranám nastavíme kapacitu na~jednotku. Řezy v~této síti odpovídají řezům v~původním +grafu. Podobně každý systém hranově disjunktních $st$-cest odpovídá toku stejné +velikosti a naopak ke~každému celočíselnému toku dovedeme najít systém disjunktních +cest (hladově tok rozkládáme na~cesty a průběžně odstraňujeme cirkulace, které +objevíme). Pak použijeme F-F větu. \qed -\s{Vìta (Mengerova, lokální vrcholová orientovaná):} -Buï $G$ orientovaný graf a $s,t$ nìjaké jeho vrcholy takové, ¾e $st\not\in E$. -Pak je velikost minimálního $st$-separátoru rovna maximálnímu poètu vrcholovì -disjunktních $st$-cest.\foot{Tím myslíme cesty disjunktní a¾ na~krajní vrcholy.} +\s{Věta (Mengerova, lokální vrcholová orientovaná):} +Buď $G$ orientovaný graf a $s,t$ nějaké jeho vrcholy takové, že $st\not\in E$. +Pak je velikost minimálního $st$-separátoru rovna maximálnímu počtu vrcholově +disjunktních $st$-cest.\foot{Tím myslíme cesty disjunktní až na~krajní vrcholy.} -\proof Podobnì jako v~dùkazu pøedchozí vìty zkonstruujeme vhodnou sí». -Tentokrát ov¹em rozdìlíme ka¾dý vrchol na~vrcholy $v^+$ a $v^-$, v¹echny hrany, které -pùvodnì vedly do~$v$, pøepojíme do~$v^+$, hrany vedoucí z~$v$ povedou z~$v^-$ -a pøidáme novou hranu z~$v^+$ do~$v^-$. V¹echny hrany budou mít jednotkové kapacity. -Toky nyní odpovídají vrcholovì disjunktním cestám, øezy v~síti separátorùm. +\proof Podobně jako v~důkazu předchozí věty zkonstruujeme vhodnou síť. +Tentokrát ovÅ¡em rozdělíme každý vrchol na~vrcholy $v^+$ a $v^-$, vÅ¡echny hrany, které +původně vedly do~$v$, přepojíme do~$v^+$, hrany vedoucí z~$v$ povedou z~$v^-$ +a přidáme novou hranu z~$v^+$ do~$v^-$. VÅ¡echny hrany budou mít jednotkové kapacity. +Toky nyní odpovídají vrcholově disjunktním cestám, řezy v~síti separátorům. \qed -\figure{vertex-split.eps}{Rozdìlení vrcholu}{\epsfxsize} +\figure{vertex-split.eps}{Rozdělení vrcholu}{\epsfxsize} -Podobnì dostaneme neorientované lokální vìty (neorientovanou hranu nahradíme -orientovanými v~obou smìrech) a z~nich pak i globální varianty popisující -$k$-souvislost grafù: +Podobně dostaneme neorientované lokální věty (neorientovanou hranu nahradíme +orientovanými v~obou směrech) a z~nich pak i globální varianty popisující +$k$-souvislost grafů: -\s{Vìta (Mengerova, globální hranová neorientovaná):} -Neorientovaný graf~$G$ je hranovì $k$-souvislý právì tehdy, kdy¾ mezi ka¾dými -dvìma vrcholy existuje alespoò~$k$ hranovì disjunktních cest. +\s{Věta (Mengerova, globální hranová neorientovaná):} +Neorientovaný graf~$G$ je hranově $k$-souvislý právě tehdy, když mezi každými +dvěma vrcholy existuje alespoň~$k$ hranově disjunktních cest. -\s{Vìta (Mengerova, globální vrcholová neorientovaná):} -Neorientovaný graf~$G$ je vrcholovì $k$-souvislý právì tehdy, kdy¾ mezi ka¾dými dvìma -vrcholy existuje alespoò~$k$ vrcholovì disjunktních cest. +\s{Věta (Mengerova, globální vrcholová neorientovaná):} +Neorientovaný graf~$G$ je vrcholově $k$-souvislý právě tehdy, když mezi každými dvěma +vrcholy existuje alespoň~$k$ vrcholově disjunktních cest. -\h{Maximální párování v bipartitním grafu} +\h{Maximální párování v bipartitním grafu} -Jiným problémem, který lze snadno pøevést na~hledání maximálního toku, je nalezení -{\I maximálního párování} v~bipartitním grafu, tedy mno¾iny hran takové, ¾e ¾ádné -dvì hrany nemají spoleèný vrchol. Maximálním míníme vzhledem k~poètu hran, +Jiným problémem, který lze snadno převést na~hledání maximálního toku, je nalezení +{\I maximálního párování} v~bipartitním grafu, tedy množiny hran takové, že žádné +dvě hrany nemají společný vrchol. Maximálním míníme vzhledem k~počtu hran, nikoliv vzhledem k~inkluzi. -Z~bipartitního grafu $(A\cup B, E)$ sestrojíme sí» obsahující v¹echny pùvodní vrcholy -a navíc dva nové vrcholy $s$ a~$t$, dále pak v¹echny pùvodní hrany orientované z~$A$ do~$B$, -nové hrany z~$s$ do~v¹ech vrcholù partity~$A$ a ze~v¹ech vrcholù partity~$B$ do~$t$. -Kapacity v¹ech hran nastavíme na jednièky: +Z~bipartitního grafu $(A\cup B, E)$ sestrojíme síť obsahující vÅ¡echny původní vrcholy +a navíc dva nové vrcholy $s$ a~$t$, dále pak vÅ¡echny původní hrany orientované z~$A$ do~$B$, +nové hrany z~$s$ do~vÅ¡ech vrcholů partity~$A$ a ze~vÅ¡ech vrcholů partity~$B$ do~$t$. +Kapacity vÅ¡ech hran nastavíme na jedničky: \fig{bipartitni.eps}{0.4\hsize} -Nyní si v¹imneme, ¾e párování v~pùvodním grafu odpovídají celoèíselným tokùm v~této síti -a ¾e velikost toku je rovna velikosti párování. Staèí tedy nalézt maximální celoèíselný -tok (tøeba F-F algoritmem) a do~párování umístit ty hrany, po~kterých nìco teèe. +Nyní si vÅ¡imneme, že párování v~původním grafu odpovídají celočíselným tokům v~této síti +a že velikost toku je rovna velikosti párování. Stačí tedy nalézt maximální celočíselný +tok (třeba F-F algoritmem) a do~párování umístit ty hrany, po~kterých něco teče. -Podobnì mù¾eme najít souvislost mezi øezy v~této síti a {\I vrcholovými pokrytími} -zadaného grafu -- to jsou mno¾iny vrcholù takové, ¾e se dotýkají ka¾dé hrany. -Tak z~F-F vìty získáme jinou standardní vìtu: +Podobně můžeme najít souvislost mezi řezy v~této síti a {\I vrcholovými pokrytími} +zadaného grafu -- to jsou množiny vrcholů takové, že se dotýkají každé hrany. +Tak z~F-F věty získáme jinou standardní větu: -\s{Vìta (Königova):} V~ka¾dém bipartitním grafu je velikost maximálního párování -rovna velikosti minimálního vrcholového pokrytí. +\s{Věta (Königova):} V~každém bipartitním grafu je velikost maximálního párování +rovna velikosti minimálního vrcholového pokrytí. \proof -Pokud je $W$ vrcholové pokrytí, musí hrany vedoucí mezi vrcholy této mno¾iny a zdrojem -a spotøebièem tvoøit stejnì velký øez, proto¾e ka¾dá $st$-cesta obsahuje alespoò -jednu hranu bipartitního grafu a ta je pokryta. Analogicky vezmeme-li libovolný -$st$-øez (ne~nutnì tokový, staèí hranový), mù¾eme ho bez zvìt¹ení upravit na~$st$-øez -pou¾ívající pouze hrany ze~$s$ a do~$t$, kterému pøímoèaøe odpovídá vrcholové pokrytí -stejné velikosti. +Pokud je $W$ vrcholové pokrytí, musí hrany vedoucí mezi vrcholy této množiny a zdrojem +a spotřebičem tvořit stejně velký řez, protože každá $st$-cesta obsahuje alespoň +jednu hranu bipartitního grafu a ta je pokryta. Analogicky vezmeme-li libovolný +$st$-řez (ne~nutně tokový, stačí hranový), můžeme ho bez zvětÅ¡ení upravit na~$st$-řez +používající pouze hrany ze~$s$ a do~$t$, kterému přímočaře odpovídá vrcholové pokrytí +stejné velikosti. \qed -Nìkteré algoritmy na~hledání maximálního párování vyu¾ívají také volné støídavé cesty: +Některé algoritmy na~hledání maximálního párování využívají také volné střídavé cesty: -\s{Definice:} {\I (Volná) støídavá cesta} v~grafu $G$ s~párováním~$M$ je cesta, která -zaèíná i konèí nespárovaným vrcholem a støídají se na~ní hrany le¾ící v~$M$ s~hranami -mimo párování. +\s{Definice:} {\I (Volná) střídavá cesta} v~grafu $G$ s~párováním~$M$ je cesta, která +začíná i končí nespárovaným vrcholem a střídají se na~ní hrany ležící v~$M$ s~hranami +mimo párování. -V¹imnìte si, ¾e pro bipartitní grafy odpovídají zlep¹ující cesty v~pøíslu¹né síti -právì volným støídavým cestám a zlep¹ení toku podél cesty odpovídá pøexorováním -párování volnou støídavou cestou. Fordùv-Fulkersonùv algoritmus tedy lze velice -snadno formulovat i v~øeèi støídavých cest. +VÅ¡imněte si, že pro bipartitní grafy odpovídají zlepÅ¡ující cesty v~přísluÅ¡né síti +právě volným střídavým cestám a zlepÅ¡ení toku podél cesty odpovídá přexorováním +párování volnou střídavou cestou. Fordův-Fulkersonův algoritmus tedy lze velice +snadno formulovat i v~řeči střídavých cest. \bye diff --git a/10-suffix/10-suffix.tex b/10-suffix/10-suffix.tex index 05fce13..ef391f4 100644 --- a/10-suffix/10-suffix.tex +++ b/10-suffix/10-suffix.tex @@ -1,188 +1,188 @@ \input ../sgr.tex -\prednaska{10}{Suffixové stromy}{} +\prednaska{10}{Suffixové stromy}{} -V~této kapitole popí¹eme jednu pozoruhodnou datovou strukturu, pomocí ní¾ doká¾eme problémy týkající -se øetìzcù pøevádìt na grafové problémy a øe¹it je tak v~lineárním èase. +V~této kapitole popíšeme jednu pozoruhodnou datovou strukturu, pomocí níž dokážeme problémy týkající +se řetězců převádět na grafové problémy a řeÅ¡it je tak v~lineárním čase. -\h{Øetìzce, trie a suffixové stromy} +\h{Řetězce, trie a suffixové stromy} \ss{Definice:} \nointerlineskip \halign{\qquad#\dotfill&~#\hfil\cr \hbox to 0.35\hsize{}\cr -$\Sigma$ & koneèná abeceda -- mno¾ina znakù \cr -\omit & (znaky budeme znaèit latinskými písmeny)\cr -$\Sigma^*$ & mno¾ina v¹ech slov nad $\Sigma$ \cr -\omit & (slova budeme znaèit øeckými písmeny)\cr -$\varepsilon$ & prázdné slovo\cr -$\vert\alpha\vert$ & délka slova $\alpha$\cr -$\alpha\beta$ & zøetìzení slov $\alpha$ a $\beta$ ($\alpha\varepsilon=\varepsilon\alpha=\alpha$)\cr -$\alpha^R$ & slovo $\alpha$ napsané pozpátku\cr -$\alpha$ je {\I prefixem} $\beta$ & $\exists\gamma: \beta=\alpha\gamma$ ($\beta$ zaèíná na~$\alpha$)\cr -$\alpha$ je {\I suffixem} $\beta$ & $\exists\gamma: \beta=\gamma\alpha$ ($\beta$ konèí na~$\alpha$)\cr -$\alpha$ je {\I podslovem} $\beta$ & $\exists\gamma,\delta: \beta=\gamma\alpha\delta$ (znaèíme $\alpha \subset \beta$)\cr -$\alpha$ je {\I vlastním prefixem} $\beta$ & je prefixem a $\alpha\ne\beta$ \cr -\omit & (analogicky vlastní suffix a podslovo)\cr +$\Sigma$ & konečná abeceda -- množina znaků \cr +\omit & (znaky budeme značit latinskými písmeny)\cr +$\Sigma^*$ & množina vÅ¡ech slov nad $\Sigma$ \cr +\omit & (slova budeme značit řeckými písmeny)\cr +$\varepsilon$ & prázdné slovo\cr +$\vert\alpha\vert$ & délka slova $\alpha$\cr +$\alpha\beta$ & zřetězení slov $\alpha$ a $\beta$ ($\alpha\varepsilon=\varepsilon\alpha=\alpha$)\cr +$\alpha^R$ & slovo $\alpha$ napsané pozpátku\cr +$\alpha$ je {\I prefixem} $\beta$ & $\exists\gamma: \beta=\alpha\gamma$ ($\beta$ začíná na~$\alpha$)\cr +$\alpha$ je {\I suffixem} $\beta$ & $\exists\gamma: \beta=\gamma\alpha$ ($\beta$ končí na~$\alpha$)\cr +$\alpha$ je {\I podslovem} $\beta$ & $\exists\gamma,\delta: \beta=\gamma\alpha\delta$ (značíme $\alpha \subset \beta$)\cr +$\alpha$ je {\I vlastním prefixem} $\beta$ & je prefixem a $\alpha\ne\beta$ \cr +\omit & (analogicky vlastní suffix a podslovo)\cr } -\s{Pozorování:} Prázdné slovo je prefixem, suffixem i podslovem ka¾dého slova vèetnì sebe sama. -Podslova jsou právì prefixy suffixù a také suffixy prefixù. +\s{Pozorování:} Prázdné slovo je prefixem, suffixem i podslovem každého slova včetně sebe sama. +Podslova jsou právě prefixy suffixů a také suffixy prefixů. -\s{Definice:} {\I Trie ($\Sigma$-strom)} pro koneènou mno¾inu slov $X\subset\Sigma^*$ je orientovaný graf $G=(V,E)$, kde: +\s{Definice:} {\I Trie ($\Sigma$-strom)} pro konečnou množinu slov $X\subset\Sigma^*$ je orientovaný graf $G=(V,E)$, kde: \itemize\relax -\:$V = \{\alpha: \alpha\hbox{ je prefixem nìjakého $\beta\in X$} \},$ +\:$V = \{\alpha: \alpha\hbox{ je prefixem nějakého $\beta\in X$} \},$ \:$(\alpha,\beta)\in E \equiv \exists x\in\Sigma: \beta=\alpha x$. \endlist -\s{Pozorování:} Trie je strom s koøenem $\varepsilon$. Jeho listy jsou slova z $X$, která nejsou vlastními prefixy jiných slov z~$X$. -Hrany si mù¾eme pøedstavit popsané písmeny, o~nì¾ prefix roz¹iøují, popisky hran na~cestì z~koøene do~vrcholu~$\alpha$ dávají právì slovo~$\alpha$. +\s{Pozorování:} Trie je strom s kořenem $\varepsilon$. Jeho listy jsou slova z $X$, která nejsou vlastními prefixy jiných slov z~$X$. +Hrany si můžeme představit popsané písmeny, o~něž prefix rozÅ¡iřují, popisky hran na~cestě z~kořene do~vrcholu~$\alpha$ dávají právě slovo~$\alpha$. -\s{Definice:} {\I Komprimovaná trie ($\Sigma^+$-strom)} vznikne z trie nahrazením maximálních nevìtvících se cest hranami. Hrany -jsou tentokrát popsané øetìzci místo jednotlivými písmeny, pøièem¾ popisky v¹ech hran vycházejících z~jednoho vrcholu se li¹í v~prvním -znaku. Vrcholùm \uv{uvnitø hran} (které padly za obì» kompresi) budeme øíkat {\I skryté vrcholy.} +\s{Definice:} {\I Komprimovaná trie ($\Sigma^+$-strom)} vznikne z trie nahrazením maximálních nevětvících se cest hranami. Hrany +jsou tentokrát popsané řetězci místo jednotlivými písmeny, přičemž popisky vÅ¡ech hran vycházejících z~jednoho vrcholu se liší v~prvním +znaku. Vrcholům \uv{uvnitř hran} (které padly za oběť kompresi) budeme říkat {\I skryté vrcholy.} -\s{Definice:} {\I Suffixový strom (ST)} pro slovo $\sigma\in\Sigma^*$ je komprimovaná trie pro $X=\{\alpha: \hbox{$\alpha$ je suffixem $\sigma$}\}$. +\s{Definice:} {\I Suffixový strom (ST)} pro slovo $\sigma\in\Sigma^*$ je komprimovaná trie pro $X=\{\alpha: \hbox{$\alpha$ je suffixem $\sigma$}\}$. -\s{Pozorování:} Vrcholy suffixového stromu (vèetnì skrytých) odpovídají prefixùm suffixù slova~$\sigma$, -tedy v¹em jeho podslovùm. Listy stromu jsou suffixy, které se v~$\sigma$ ji¾ nikde jinde nevyskytují -(takovým suffixùm budeme øíkat {\I nevnoøené}). Vnitøní vrcholy odpovídají {\I vìtvícím podslovùm,} -tedy podslovùm $\alpha\subset\sigma$ takovým, ¾e $\alpha a\subset\sigma$ i $\alpha b\subset\sigma$ -pro nìjaké dva rùzné znaky~$a$,~$b$. +\s{Pozorování:} Vrcholy suffixového stromu (včetně skrytých) odpovídají prefixům suffixů slova~$\sigma$, +tedy vÅ¡em jeho podslovům. Listy stromu jsou suffixy, které se v~$\sigma$ již nikde jinde nevyskytují +(takovým suffixům budeme říkat {\I nevnořené}). Vnitřní vrcholy odpovídají {\I větvícím podslovům,} +tedy podslovům $\alpha\subset\sigma$ takovým, že $\alpha a\subset\sigma$ i $\alpha b\subset\sigma$ +pro nějaké dva různé znaky~$a$,~$b$. -Nìkdy mù¾e být nepraktické, ¾e nìkteré suffixy neodpovídají listùm (proto¾e jsou vnoøené), ale -s~tím se mù¾eme snadno vypoøádat: pøidáme na~konec slova~$\sigma$ nìjaký znak~$\$$, který se nikde -jinde nevyskytuje. Neprázdné suffixy slova $\sigma\$$ odpovídají suffixùm slova~$\sigma$ -a ¾ádný z~nich nemù¾e být vnoøený. Takový suffixový strom budeme znaèit ST\$. +Někdy může být nepraktické, že některé suffixy neodpovídají listům (protože jsou vnořené), ale +s~tím se můžeme snadno vypořádat: přidáme na~konec slova~$\sigma$ nějaký znak~$\$$, který se nikde +jinde nevyskytuje. Neprázdné suffixy slova $\sigma\$$ odpovídají suffixům slova~$\sigma$ +a žádný z~nich nemůže být vnořený. Takový suffixový strom budeme značit ST\$. -\s{Pøíklad:} +\s{Příklad:} -\figure{baraba.eps}{Suffixy slova \uv{baraba}: trie, suffixový strom, ST s~dolarem}{\epsfxsize} +\figure{baraba.eps}{Suffixy slova \uv{baraba}: trie, suffixový strom, ST s~dolarem}{\epsfxsize} -\>Nyní jak je to s~konstrukcí suffixových stromù: +\>Nyní jak je to s~konstrukcí suffixových stromů: -\s{Lemma:} Suffixový strom pro slovo $\sigma$ délky $n$ je reprezentovatelný v~prostoru $\O(n)$. +\s{Lemma:} Suffixový strom pro slovo $\sigma$ délky $n$ je reprezentovatelný v~prostoru $\O(n)$. -\proof Strom má $\O(n)$ listù a ka¾dý vnitøní vrchol má alespoò $2$ syny, tak¾e vnitøních -vrcholù je také $\O(n)$. Hran je rovnì¾ lineárnì. Nálepky na~hranách staèí popsat -poèáteèní a koncovou pozicí v~$\sigma$. +\proof Strom má $\O(n)$ listů a každý vnitřní vrchol má alespoň $2$ syny, takže vnitřních +vrcholů je také $\O(n)$. Hran je rovněž lineárně. Nálepky na~hranách stačí popsat +počáteční a koncovou pozicí v~$\sigma$. \qed -\s{Vìta:} Suffixový strom pro slovo $\sigma$ délky $n$ lze sestrojit v~èase $\O(n)$. +\s{Věta:} Suffixový strom pro slovo $\sigma$ délky $n$ lze sestrojit v~čase $\O(n)$. -\proof Ve~zbytku této kapitoly pøedvedeme dvì rùzné konstrukce v~lineárním èase. +\proof Ve~zbytku této kapitoly předvedeme dvě různé konstrukce v~lineárním čase. \qed -\s{Aplikace} -- co v¹e doká¾eme v~lineárním èase, kdy¾ umíme lineárnì konstruovat ST: +\s{Aplikace} -- co vÅ¡e dokážeme v~lineárním čase, když umíme lineárně konstruovat ST: \nobreak \numlist\ndotted -\:{\I Inverzní vyhledávání} (tj. pøedzpracujeme si v~lineárním èase text a pak umíme pro libovolné -slovo~$\alpha$ v~èase $\O(\vert\alpha\vert)$ rozhodnout, zda se v~textu vyskytuje)\foot{Èili pøesný -opak toho, co~umí vyhledávací automat -- ten si pøedzpracovává dotaz.} -- staèí sestrojit~ST -a pak jej procházet od~koøene. Také umíme najít v¹echny výskyty (odpovídají suffixùm, které mají -jako prefix hledané slovo, tak¾e staèí vytvoøit ST\$ a vypsat v¹echny listy pod -nalezeným vrcholem) nebo pøímo vrátit jejich poèet (pøedpoèítáme si pomocí DFS pro ka¾dý vrchol, -kolik pod ním le¾í listù). - -\:{\I Nejdel¹í opakující se podslovo} -- takové podslovo je v~ST\$ nutnì vìtvící, tak¾e staèí -najít vnitøní vrchol s~nejvìt¹í {\I písmenkovou hloubkou} (tj. hloubkou mìøenou ve~znacích -místo ve~hranách). - -\:{\I Histogram èetností podslov délky~$k$} -- rozøízneme ST\$ v~písmenkové hloubce~$k$ a spoèítáme, -kolik pùvodních listù je pod ka¾dým novým. - -\:{\I Nejdel¹í spoleèné podslovo} slov~$\alpha$ a $\beta$ -- postavíme ST pro slovo $\alpha\$_1\beta\$_2$, -jeho listy odpovídají suffixùm slov $\alpha$ a $\beta$. Tak¾e staèí pomocí DFS najít nejhlub¹í vnitøní -vrchol, pod kterým se vyskytují listy pro~$\alpha$ i $\beta$. Podobnì mù¾eme sestrojit ST\$ pro libovolnou -mno¾inu slov.\foot{Jen si musíme dát pozor, abychom si moc nezvìt¹ili abecedu; jak moc si ji -mù¾eme dovolit zvìt¹it, vyplyne z~konkrétních konstrukcí.} - -\:{\I Nejdel¹í palindromické podslovo} (tj. takové $\beta\subset\alpha$, pro nì¾ je $\beta^R=\beta$) --- postavíme spoleèný ST\$ pro slova $\alpha$ a $\alpha^R$. Postupnì procházíme pøes v¹echny mo¾né støedy -palindromického podslova a v¹imneme si, ¾e takové slovo je pro ka¾dý støed nejdel¹ím spoleèným -prefixem podslova od~tohoto bodu do~konce a podslova od~tohoto bodu pozpátku k~zaèátku, -èili nìjakého suffixu $\alpha$ a nìjakého suffixu $\alpha^R$. Tyto suffixy ov¹em odpovídají -listùm sestrojeného ST a jejich nejdel¹í spoleèný prefix je nejbli¾¹ím spoleèným pøedchùdcem -ve~stromu, tak¾e staèí pro strom vybudovat datovou strukturu pro spoleèné pøedchùdce -a s~její pomocí doká¾eme jeden støed prozkoumat v~konstantním èase. - -\:{\I Burrows-Wheelerova Transformace} \cite{burrows:bwt} -- jejím základem je lexikografické setøídìní v¹ech -rotací slova~$\sigma$, co¾ zvládneme sestrojením ST pro slovo~$\sigma\sigma$, jeho -uøíznutím v~písmenkové hloubce~$\vert\sigma\vert$ a vypsáním novì vzniklých listù v~poøadí +\:{\I Inverzní vyhledávání} (tj. předzpracujeme si v~lineárním čase text a pak umíme pro libovolné +slovo~$\alpha$ v~čase $\O(\vert\alpha\vert)$ rozhodnout, zda se v~textu vyskytuje)\foot{Čili přesný +opak toho, co~umí vyhledávací automat -- ten si předzpracovává dotaz.} -- stačí sestrojit~ST +a pak jej procházet od~kořene. Také umíme najít vÅ¡echny výskyty (odpovídají suffixům, které mají +jako prefix hledané slovo, takže stačí vytvořit ST\$ a vypsat vÅ¡echny listy pod +nalezeným vrcholem) nebo přímo vrátit jejich počet (předpočítáme si pomocí DFS pro každý vrchol, +kolik pod ním leží listů). + +\:{\I Nejdelší opakující se podslovo} -- takové podslovo je v~ST\$ nutně větvící, takže stačí +najít vnitřní vrchol s~největší {\I písmenkovou hloubkou} (tj. hloubkou měřenou ve~znacích +místo ve~hranách). + +\:{\I Histogram četností podslov délky~$k$} -- rozřízneme ST\$ v~písmenkové hloubce~$k$ a spočítáme, +kolik původních listů je pod každým novým. + +\:{\I Nejdelší společné podslovo} slov~$\alpha$ a $\beta$ -- postavíme ST pro slovo $\alpha\$_1\beta\$_2$, +jeho listy odpovídají suffixům slov $\alpha$ a $\beta$. Takže stačí pomocí DFS najít nejhlubší vnitřní +vrchol, pod kterým se vyskytují listy pro~$\alpha$ i $\beta$. Podobně můžeme sestrojit ST\$ pro libovolnou +množinu slov.\foot{Jen si musíme dát pozor, abychom si moc nezvětÅ¡ili abecedu; jak moc si ji +můžeme dovolit zvětÅ¡it, vyplyne z~konkrétních konstrukcí.} + +\:{\I Nejdelší palindromické podslovo} (tj. takové $\beta\subset\alpha$, pro něž je $\beta^R=\beta$) +-- postavíme společný ST\$ pro slova $\alpha$ a $\alpha^R$. Postupně procházíme přes vÅ¡echny možné středy +palindromického podslova a vÅ¡imneme si, že takové slovo je pro každý střed nejdelším společným +prefixem podslova od~tohoto bodu do~konce a podslova od~tohoto bodu pozpátku k~začátku, +čili nějakého suffixu $\alpha$ a nějakého suffixu $\alpha^R$. Tyto suffixy ovÅ¡em odpovídají +listům sestrojeného ST a jejich nejdelší společný prefix je nejbližším společným předchůdcem +ve~stromu, takže stačí pro strom vybudovat datovou strukturu pro společné předchůdce +a s~její pomocí dokážeme jeden střed prozkoumat v~konstantním čase. + +\:{\I Burrows-Wheelerova Transformace} \cite{burrows:bwt} -- jejím základem je lexikografické setřídění vÅ¡ech +rotací slova~$\sigma$, což zvládneme sestrojením ST pro slovo~$\sigma\sigma$, jeho +uříznutím v~písmenkové hloubce~$\vert\sigma\vert$ a vypsáním nově vzniklých listů v~pořadí \uv{zleva doprava}. \endlist -\s{Cvièení:} Zkuste vymyslet co nejlep¹í algoritmy pro tyto problémy bez pou¾ití~ST. +\s{Cvičení:} Zkuste vymyslet co nejlepší algoritmy pro tyto problémy bez použití~ST. -\h{Suffixová pole} +\h{Suffixová pole} -\>V~nìkterých pøípadech se hodí místo suffixového stromu pou¾ívat kompaktnìj¹í datové struktury. +\>V~některých případech se hodí místo suffixového stromu používat kompaktnější datové struktury. -\s{Notace:} Pro slovo $\sigma$ bude $\sigma[i]$ znaèit jeho $i$-tý znak (èíslujeme od~nuly), -$\sigma[i:j]$ pak podslovo $\sigma[i]\sigma[i+1]\ldots\sigma[j-1]$. Libovolnou z~mezí mù¾eme vynechat, proto -$\sigma[i:{}]$ bude suffix od~$i$ do~konce a $\sigma[{}:j]$ prefix od~zaèátku do~$j-1$. -Pokud $j\le i$, definujeme $\sigma[i:j]$ jako prázdné slovo, tak¾e prázdný suffix mù¾eme -napøíklad zapsat jako $\sigma[\vert\sigma\vert:{}].$ +\s{Notace:} Pro slovo $\sigma$ bude $\sigma[i]$ značit jeho $i$-tý znak (číslujeme od~nuly), +$\sigma[i:j]$ pak podslovo $\sigma[i]\sigma[i+1]\ldots\sigma[j-1]$. Libovolnou z~mezí můžeme vynechat, proto +$\sigma[i:{}]$ bude suffix od~$i$ do~konce a $\sigma[{}:j]$ prefix od~začátku do~$j-1$. +Pokud $j\le i$, definujeme $\sigma[i:j]$ jako prázdné slovo, takže prázdný suffix můžeme +například zapsat jako $\sigma[\vert\sigma\vert:{}].$ -${\rm LCP}(\alpha,\beta)$ bude znaèit délku nejdel¹ího spoleèného prefixu slov $\alpha$ a $\beta$, -èili nejvìt¹í $i\le \vert\alpha\vert,\vert\beta\vert$ takové, ¾e $\alpha[{}:i]=\beta[{}:i]$. +${\rm LCP}(\alpha,\beta)$ bude značit délku nejdelšího společného prefixu slov $\alpha$ a $\beta$, +čili největší $i\le \vert\alpha\vert,\vert\beta\vert$ takové, že $\alpha[{}:i]=\beta[{}:i]$. -\s{Definice:} {\I Suffixové pole (Suffix Array)} $A_\sigma$ pro slovo $\sigma$ délky~$n$ je posloupnost v¹ech suffixù -slova~$\sigma$ v~lexikografickém poøadí. Mù¾eme ho reprezentovat napøíklad jako permutaci $A$ èísel -$0,\ldots,n$, pro ní¾ $\sigma[A[0]:{}] < \sigma[A[1]:{}] < \ldots < \sigma[A[n]:{}]$. +\s{Definice:} {\I Suffixové pole (Suffix Array)} $A_\sigma$ pro slovo $\sigma$ délky~$n$ je posloupnost vÅ¡ech suffixů +slova~$\sigma$ v~lexikografickém pořadí. Můžeme ho reprezentovat například jako permutaci $A$ čísel +$0,\ldots,n$, pro níž $\sigma[A[0]:{}] < \sigma[A[1]:{}] < \ldots < \sigma[A[n]:{}]$. -\s{Definice:} {\I Pole nejdel¹ích spoleèných prefixù (Longest Common Prefix Array)} $L_\sigma$ pro slovo $\sigma$ je posloupnost, -v~ní¾ $L_\sigma[i]:={\rm LCP}(A_\sigma[i],A_\sigma[i+1])$. +\s{Definice:} {\I Pole nejdelších společných prefixů (Longest Common Prefix Array)} $L_\sigma$ pro slovo $\sigma$ je posloupnost, +v~níž $L_\sigma[i]:={\rm LCP}(A_\sigma[i],A_\sigma[i+1])$. -\s{Vìta:} Suffixový strom pro slovo $\sigma\$$ a dvojici $(A_\sigma,L_\sigma)$ na sebe lze -v~lineárním èase pøevádìt. +\s{Věta:} Suffixový strom pro slovo $\sigma\$$ a dvojici $(A_\sigma,L_\sigma)$ na sebe lze +v~lineárním čase převádět. -\proof Kdy¾ projdeme ST($\sigma\$$) do hloubky, poøadí listù odpovídá posloupnosti $A_\sigma$ a písmenkové hloubky vnitøních -vrcholù v~inorderu odpovídají $L_\sigma$. Naopak ST($\sigma\$$) získáme tak, ¾e sestrojíme kartézský strom -pro~$L_\sigma$ (získáme vnitøní vrcholy ST), doplníme do~nìj listy, pøiøadíme jim suffixy podle~$A_\sigma$ -a nakonec podle listù rekonstruujeme nálepky hran. +\proof Když projdeme ST($\sigma\$$) do hloubky, pořadí listů odpovídá posloupnosti $A_\sigma$ a písmenkové hloubky vnitřních +vrcholů v~inorderu odpovídají $L_\sigma$. Naopak ST($\sigma\$$) získáme tak, že sestrojíme kartézský strom +pro~$L_\sigma$ (získáme vnitřní vrcholy ST), doplníme do~něj listy, přiřadíme jim suffixy podle~$A_\sigma$ +a nakonec podle listů rekonstruujeme nálepky hran. \qed -\h{Rekurzivní konstrukce} +\h{Rekurzivní konstrukce} -\>Uká¾eme algoritmus, který pro slovo $\sigma\in\Sigma^*$ délky~$n$ sestrojí jeho suffixové pole -a LCP pole v~èase $\O(n+{\rm Sort}(n,\Sigma))$, kde ${\rm Sort}(\ldots)$ je èas potøebný pro setøídìní -$n$~symbolù z~abecedy~$\Sigma$. V~kombinaci s~pøedchozími výsledky tedy dostaneme lineární konstrukci -ST($\sigma$) pro libovolnou fixní abecedu. +\>Ukážeme algoritmus, který pro slovo $\sigma\in\Sigma^*$ délky~$n$ sestrojí jeho suffixové pole +a LCP pole v~čase $\O(n+{\rm Sort}(n,\Sigma))$, kde ${\rm Sort}(\ldots)$ je čas potřebný pro setřídění +$n$~symbolů z~abecedy~$\Sigma$. V~kombinaci s~předchozími výsledky tedy dostaneme lineární konstrukci +ST($\sigma$) pro libovolnou fixní abecedu. -\s{Algoritmus:} (Konstrukce $A$ a $L$ podle Kärkkäinena a Sanderse \cite{karkkainen03simple}) +\s{Algoritmus:} (Konstrukce $A$ a $L$ podle Kärkkäinena a Sanderse \cite{karkkainen03simple}) \algo -\:Redukujeme abecedu na~$1\ldots n$: ve~vstupním slovu je nejvý¹e $n$ rùzných znakù, -tak¾e je staèí setøídit a pøeèíslovat. +\:Redukujeme abecedu na~$1\ldots n$: ve~vstupním slovu je nejvýše $n$ různých znaků, +takže je stačí setřídit a přečíslovat. -\:Definujeme slova $\sigma_0$, $\sigma_1$, $\sigma_2$ následovnì: +\:Definujeme slova $\sigma_0$, $\sigma_1$, $\sigma_2$ následovně: $$\eqalign{ \sigma_0[i] &:= \left<\sigma[3i],\sigma[3i+1],\sigma[3i+2]\right>\cr \sigma_1[i] &:= \left<\sigma[3i+1],\sigma[3i+2],\sigma[3i+3]\right>\cr \sigma_2[i] &:= \left<\sigma[3i+2],\sigma[3i+3],\sigma[3i+4]\right>\cr }$$ -V¹echna $\sigma_k$ jsou slova délky $\approx n/3$ nad~abecedou velikosti $n^3$. Dovolíme -si mírnì zneu¾ívat notaci a pou¾ívat symbol $\sigma_k$ i jejich pøepis do~abecedy pùvodní. +VÅ¡echna $\sigma_k$ jsou slova délky $\approx n/3$ nad~abecedou velikosti $n^3$. Dovolíme +si mírně zneužívat notaci a používat symbol $\sigma_k$ i jejich přepis do~abecedy původní. -\:Zavoláme algoritmus rekurzivnì na slovo $\sigma_0\sigma_1$, èím¾ získáme $A_{01}$ a $L_{01}$. -(Suffixy slova $\sigma_0\sigma_1$ odpovídají suffixùm slov $\sigma_0$ a~$\sigma_1$.) +\:Zavoláme algoritmus rekurzivně na slovo $\sigma_0\sigma_1$, čímž získáme $A_{01}$ a $L_{01}$. +(Suffixy slova $\sigma_0\sigma_1$ odpovídají suffixům slov $\sigma_0$ a~$\sigma_1$.) -\:Spoèítáme pole $P_0$ a $P_1$, která nám budou øíkat, kde se v~$A_{01}$ vyskytuje -který suffix slov $\sigma_0$ a~$\sigma_1$. Tedy $A_{01}[P_0[i]]=i$, $A_{01}[P_1[i]] = i+\vert\sigma_0\vert$. -Jinými slovy, $P_0$ a~$P_1$ budou èásti inverzní permutace k~$A_{01}$. V¹imnìte si, -¾e platí $P_i[x] < P_j[y]$ právì tehdy, kdy¾ $\sigma_i[x:{}] < \sigma_j[y:{}]$, tak¾e -suffixy slov $\sigma_0$ a~$\sigma_1$ od této chvíle umíme porovnávat v~èase~$\O(1)$. +\:Spočítáme pole $P_0$ a $P_1$, která nám budou říkat, kde se v~$A_{01}$ vyskytuje +který suffix slov $\sigma_0$ a~$\sigma_1$. Tedy $A_{01}[P_0[i]]=i$, $A_{01}[P_1[i]] = i+\vert\sigma_0\vert$. +Jinými slovy, $P_0$ a~$P_1$ budou části inverzní permutace k~$A_{01}$. VÅ¡imněte si, +že platí $P_i[x] < P_j[y]$ právě tehdy, když $\sigma_i[x:{}] < \sigma_j[y:{}]$, takže +suffixy slov $\sigma_0$ a~$\sigma_1$ od této chvíle umíme porovnávat v~čase~$\O(1)$. -\:Vytvoøíme~$A_2$ (suffixové pole pro~$\sigma_2$): Jeliko¾ $\sigma_2[i:{}] = \sigma[3i+2:{}] = \sigma[3i+2]\sigma[3i+3:\nobreak{}\nobreak] = \sigma[3i+2]\sigma_0[i+1:{}]$, -odpovídá lexikografické poøadí suffixù $\sigma_2[i:{}]$ poøadí dvojic $(\sigma[3i+2],P_0[i+1])$. -Tyto dvojice ov¹em mù¾eme setøídit dvìma prùchody pøihrádkového tøídìní. +\:Vytvoříme~$A_2$ (suffixové pole pro~$\sigma_2$): Jelikož $\sigma_2[i:{}] = \sigma[3i+2:{}] = \sigma[3i+2]\sigma[3i+3:\nobreak{}\nobreak] = \sigma[3i+2]\sigma_0[i+1:{}]$, +odpovídá lexikografické pořadí suffixů $\sigma_2[i:{}]$ pořadí dvojic $(\sigma[3i+2],P_0[i+1])$. +Tyto dvojice ovÅ¡em můžeme setřídit dvěma průchody přihrádkového třídění. -\:Slijeme $A_{01}$ a~$A_2$ do~$A$: sléváme dvì setøídìné posloupnosti, -tak¾e staèí umìt jejich prvky v~konstantním èase porovnat: +\:Slijeme $A_{01}$ a~$A_2$ do~$A$: sléváme dvě setříděné posloupnosti, +takže stačí umět jejich prvky v~konstantním čase porovnat: $$\eqalign{ \sigma_0[i:{}] < \sigma_2[j:{}] \Leftrightarrow{} &\sigma[3i:{}] < \sigma[3j+2:{}] \cr \Leftrightarrow{} &\sigma[3i]\,\sigma_1[i:{}] < \sigma[3j+2]\,\sigma_0[j+1:{}],\cr @@ -190,191 +190,191 @@ $$\eqalign{ \Leftrightarrow{} &\sigma[3i+1]\,\sigma[3i+2]\,\sigma_0[i+1:{}] < \cr &\sigma[3j+2]\,\sigma[3j+3]\,\sigma_1[j+1:{}].\cr }$$ -Poka¾dé tedy porovnáme nejvý¹e dvì dvojice znakù a pak dvojici suffixù slov $\sigma_0$ a $\sigma_1$, -k~èemu¾ nám pomohou pole $P_0$ a~$P_1$. +Pokaždé tedy porovnáme nejvýše dvě dvojice znaků a pak dvojici suffixů slov $\sigma_0$ a $\sigma_1$, +k~čemuž nám pomohou pole $P_0$ a~$P_1$. -\:Dopoèítáme $L$: - \::Pokud v~$A$ sousedí suffix slova~$\sigma_{0,1}$ se suffixem slova~$\sigma_{0,1}$, - sousedí tyto dva suffixy i v~$A_{01}$, tak¾e jejich LCP najdeme pøímo v~$L$. - \::Setkají-li se dva suffixy slova~$\sigma_2$, v¹imneme si, ¾e +\:Dopočítáme $L$: + \::Pokud v~$A$ sousedí suffix slova~$\sigma_{0,1}$ se suffixem slova~$\sigma_{0,1}$, + sousedí tyto dva suffixy i v~$A_{01}$, takže jejich LCP najdeme přímo v~$L$. + \::Setkají-li se dva suffixy slova~$\sigma_2$, vÅ¡imneme si, že $\sigma_2[i:{}] = \sigma[3i+2:\nobreak{}] = \sigma[3i+2]\,\sigma_0[i+1:{}]$. - ${\rm LCP}(\sigma_2[i:{}],\sigma_2[j:{}])$ je tedy buïto~0 (pokud $\sigma[3i+2]\ne\sigma[3j+2]$), - nebo $1+3\cdot{\rm LCP}(\sigma_0[i+1:{}],\sigma_0[j+1:{}])$, pøípadnì toté¾ zvý¹ené - o~1 nebo~2, pokud se trojznaky v~$\sigma_0$ následující po LCP zèásti shodují. - Pøitom ${\rm LCP}(\sigma_0[p:{}],\sigma_0[q:{}])$ spoèítáme pomocí~$L$. - Je to toti¾ minimum intervalu v~$L$ mezi indexy $P_0[p]$ a~$P_0[q]$. To zjistíme - v~konstantním èase pomocí struktury pro intervalová minima. - \::Pokud se setká suffix slova~$\sigma_{0,1}$ se suffixem slova~$\sigma_2$, staèí - tyto suffixy pøepsat podobnì jako v~6.~kroku a problém tím opìt pøevést - na výpoèet LCP dvou suffixù slov~$\sigma_{0,1}$. + ${\rm LCP}(\sigma_2[i:{}],\sigma_2[j:{}])$ je tedy buďto~0 (pokud $\sigma[3i+2]\ne\sigma[3j+2]$), + nebo $1+3\cdot{\rm LCP}(\sigma_0[i+1:{}],\sigma_0[j+1:{}])$, případně totéž zvýšené + o~1 nebo~2, pokud se trojznaky v~$\sigma_0$ následující po LCP zčásti shodují. + Přitom ${\rm LCP}(\sigma_0[p:{}],\sigma_0[q:{}])$ spočítáme pomocí~$L$. + Je to totiž minimum intervalu v~$L$ mezi indexy $P_0[p]$ a~$P_0[q]$. To zjistíme + v~konstantním čase pomocí struktury pro intervalová minima. + \::Pokud se setká suffix slova~$\sigma_{0,1}$ se suffixem slova~$\sigma_2$, stačí + tyto suffixy přepsat podobně jako v~6.~kroku a problém tím opět převést + na výpočet LCP dvou suffixů slov~$\sigma_{0,1}$. \endalgo -\s{Analýza èasové slo¾itosti:} Tøídìní napoprvé trvá ${\rm Sort}(n,\Sigma)$, ve~v¹ech -rekurzivních voláních u¾ je lineární (trojice èísel velikosti $\O(n)$ mù¾eme tøídit tøíprùchodovým -pøihrádkovým tøídìním s~$\O(n)$ pøihrádkami). Z~toho dostáváme: +\s{Analýza časové složitosti:} Třídění napoprvé trvá ${\rm Sort}(n,\Sigma)$, ve~vÅ¡ech +rekurzivních voláních už je lineární (trojice čísel velikosti $\O(n)$ můžeme třídit tříprůchodovým +přihrádkovým tříděním s~$\O(n)$ přihrádkami). Z~toho dostáváme: $$T(n) = T(2/3\cdot n) + \O(n),~\hbox{a tedy}~T(n)=\O(n).$$ \qed -\h{Ukkonenova inkrementální konstrukce} +\h{Ukkonenova inkrementální konstrukce} -\>Ukkonen popsal algoritmus \cite{ukkonen95line} pro konstrukci suffixového stromu bez dolarù, -pracující inkrementálnì: Zaène se stromem pro prázdné slovo a postupnì na konec slova pøidává -dal¹í znaky a pøepoèítává strom. Ka¾dý znak pøitom pøidá v~amortizovanì konstantním èase. -Pro slovo~$\sigma$ tedy doká¾e sestrojit ST v~èase $\O(\vert\sigma\vert)$. +\>Ukkonen popsal algoritmus \cite{ukkonen95line} pro konstrukci suffixového stromu bez dolarů, +pracující inkrementálně: Začne se stromem pro prázdné slovo a postupně na konec slova přidává +další znaky a přepočítává strom. Každý znak přitom přidá v~amortizovaně konstantním čase. +Pro slovo~$\sigma$ tedy dokáže sestrojit ST v~čase $\O(\vert\sigma\vert)$. -Budeme pøedpokládat, ¾e hrany vedoucí z~jednoho vrcholu je mo¾né indexovat jejich -prvními písmeny -- to bezpeènì platí, pokud je abeceda pevná; není-li, mù¾eme -si pomoci he¹ováním. +Budeme předpokládat, že hrany vedoucí z~jednoho vrcholu je možné indexovat jejich +prvními písmeny -- to bezpečně platí, pokud je abeceda pevná; není-li, můžeme +si pomoci heÅ¡ováním. -\s{Pozorování:} Kdy¾ slovo~$\sigma$ roz¹íøíme na~$\sigma a$, ST se zmìní následovnì: +\s{Pozorování:} Když slovo~$\sigma$ rozšíříme na~$\sigma a$, ST se změní následovně: \numlist\ndotted -\:V¹echny stávající vrcholy stromu (vèetnì skrytých) odpovídají podslovùm slova~$\sigma$. - Ta jsou i podslovy $\sigma a$, tak¾e se budou nacházet i v~novém stromu. -\:Pokud $\beta$ bylo vìtvící slovo, zùstane nadále vìtvící -- tedy vnitøní vrcholy ve~stromu zùstanou. -\:Ka¾dý nový suffix~$\beta a$ vznikne prodlou¾ením nìjakého pùvodního suffixu~$\beta$. Pøitom: +\:VÅ¡echny stávající vrcholy stromu (včetně skrytých) odpovídají podslovům slova~$\sigma$. + Ta jsou i podslovy $\sigma a$, takže se budou nacházet i v~novém stromu. +\:Pokud $\beta$ bylo větvící slovo, zůstane nadále větvící -- tedy vnitřní vrcholy ve~stromu zůstanou. +\:Každý nový suffix~$\beta a$ vznikne prodloužením nějakého původního suffixu~$\beta$. Přitom: \itemize\ibull - \:Pokud byl~$\beta$ nevnoøený suffix (èili byl reprezentovaný listem), ani $\beta a$ - nebude vnoøený. Z~toho víme, ¾e listy zùstanou listy, pouze jim potøebujeme prodlou¾it - nálepky. Aby to netrvalo pøíli¹ dlouho, zavedeme {\I otevøené hrany,} jejich¾ nálepka - øíká \uv{od~pozice~$i$ do konce}. Listy se tak o~sebe postarají samy. - \:Pokud $\beta$ byl vnoøený suffix (tj. vnitøní èi skrytý vrchol): + \:Pokud byl~$\beta$ nevnořený suffix (čili byl reprezentovaný listem), ani $\beta a$ + nebude vnořený. Z~toho víme, že listy zůstanou listy, pouze jim potřebujeme prodloužit + nálepky. Aby to netrvalo příliÅ¡ dlouho, zavedeme {\I otevřené hrany,} jejichž nálepka + říká \uv{od~pozice~$i$ do konce}. Listy se tak o~sebe postarají samy. + \:Pokud $\beta$ byl vnořený suffix (tj. vnitřní či skrytý vrchol): \itemize\ibull - \:Buï se $\beta a$ vyskytuje v~$\sigma$, a tím pádem je to vnoøený suffix nového slova - a strom není nutné upravovat; - \:nebo se $\beta a$ v~$\sigma$ nevyskytuje -- tehdy pro nìj musíme zalo¾it nový list - s~otevøenou hranou a pøípadnì i nový vnitøní vrchol, pod ním¾ bude tento list pøipojen. + \:Buď se $\beta a$ vyskytuje v~$\sigma$, a tím pádem je to vnořený suffix nového slova + a strom není nutné upravovat; + \:nebo se $\beta a$ v~$\sigma$ nevyskytuje -- tehdy pro něj musíme založit nový list + s~otevřenou hranou a případně i nový vnitřní vrchol, pod nímž bude tento list připojen. \endlist \endlist \endlist -Víme tedy, co v¹echno je pøi roz¹íøení slova potøeba ve~stromu upravit. -Zbývá vyøe¹it, jak to udìlat efektivnì. +Víme tedy, co vÅ¡echno je při rozšíření slova potřeba ve~stromu upravit. +Zbývá vyřeÅ¡it, jak to udělat efektivně. -\s{Vnoøené suffixy:} -Pøedev¹ím potøebujeme umìt rozpoznat, které suffixy jsou vnoøené a které nikoliv. -K~tomu se hodí v¹imnout si, ¾e vnoøené suffixy tvoøí souvislý úsek: +\s{Vnořené suffixy:} +Především potřebujeme umět rozpoznat, které suffixy jsou vnořené a které nikoliv. +K~tomu se hodí vÅ¡imnout si, že vnořené suffixy tvoří souvislý úsek: {\narrower -\s{Lemma:} Je-li $\alpha$ vnoøený suffix slova~$\sigma$ a $\beta$ je suffix slova~$\alpha$, -pak $\beta$ je v~$\sigma$ také vnoøený. +\s{Lemma:} Je-li $\alpha$ vnořený suffix slova~$\sigma$ a $\beta$ je suffix slova~$\alpha$, +pak $\beta$ je v~$\sigma$ také vnořený. \proof -Ve~slovì sigma se vyskytuje $\alpha x$ a $\alpha y$ pro nìjaké dva rùzné znaky $x$ a~$y$. -Ka¾dý z~tìchto výskytù pøitom konèí výskytem slova~$\beta$, jednou následovaným~$x$, -podruhé~$y$. +Ve~slově sigma se vyskytuje $\alpha x$ a $\alpha y$ pro nějaké dva různé znaky $x$ a~$y$. +Každý z~těchto výskytů přitom končí výskytem slova~$\beta$, jednou následovaným~$x$, +podruhé~$y$. \qed } -\>Staèí si tedy zapamatovat nejdel¹í vnoøený suffix slova~$\sigma$. Tomu budeme øíkat -{\I aktivní suffix} a budeme ho znaèit $\alpha(\sigma)$. Libovolný suffix~$\beta\subseteq\sigma$ -pak bude vnoøený právì tehdy, kdy¾ $\vert\beta\vert \le \vert\alpha(\sigma)\vert$. +\>Stačí si tedy zapamatovat nejdelší vnořený suffix slova~$\sigma$. Tomu budeme říkat +{\I aktivní suffix} a budeme ho značit $\alpha(\sigma)$. Libovolný suffix~$\beta\subseteq\sigma$ +pak bude vnořený právě tehdy, když $\vert\beta\vert \le \vert\alpha(\sigma)\vert$. -Aktivní suffix tedy tvoøí hranici mezi nevnoøenými a vnoøenými suffixy. Jak se tato -hranice posune, kdy¾ slovo~$\sigma$ roz¹íøíme? Na to je odpovìï snadná: +Aktivní suffix tedy tvoří hranici mezi nevnořenými a vnořenými suffixy. Jak se tato +hranice posune, když slovo~$\sigma$ rozšíříme? Na to je odpověď snadná: {\narrower -\s{Lemma:} Pro ka¾dé $\sigma$, $a$ platí: $\alpha(\sigma a)$ je suffixem $\alpha(\sigma)a.$ +\s{Lemma:} Pro každé $\sigma$, $a$ platí: $\alpha(\sigma a)$ je suffixem $\alpha(\sigma)a.$ \proof -$\alpha(\sigma a)$ i $\alpha(\sigma)a$ jsou suffixy slova $\sigma a$, a~proto staèí porovnat jejich délky. -Slovo $\beta := \hbox{\uv{$\alpha(\sigma a)$ bez koncového~$a$}}$ je vnoøeným suffixem v~$\sigma$, tak¾e -$\vert\beta\vert \le \vert\alpha(\sigma)\vert$, a~tedy také $\vert\alpha(\sigma a)\vert = \vert\beta a\vert \le \vert\alpha(\sigma)a\vert$. +$\alpha(\sigma a)$ i $\alpha(\sigma)a$ jsou suffixy slova $\sigma a$, a~proto stačí porovnat jejich délky. +Slovo $\beta := \hbox{\uv{$\alpha(\sigma a)$ bez koncového~$a$}}$ je vnořeným suffixem v~$\sigma$, takže +$\vert\beta\vert \le \vert\alpha(\sigma)\vert$, a~tedy také $\vert\alpha(\sigma a)\vert = \vert\beta a\vert \le \vert\alpha(\sigma)a\vert$. \qed } -\>Hranice se tedy mù¾e posouvat pouze doprava, pøípadnì zùstat na místì. -Toho lze snadno vyu¾ít. +\>Hranice se tedy může posouvat pouze doprava, případně zůstat na místě. +Toho lze snadno využít. -\s{Idea algoritmu:} Udr¾ujeme si $\alpha=\alpha(\sigma)$ a pøi pøidání znaku $a$ zkontrolujeme, -zda $\alpha a$ je stále vnoøený suffix. Pokud ano, nic se nemìní, pokud ne, pøidáme nový list -a pøípadnì také vnitøní vrchol, $\alpha$ zkrátíme zleva o~znak a testujeme dál. +\s{Idea algoritmu:} Udržujeme si $\alpha=\alpha(\sigma)$ a při přidání znaku $a$ zkontrolujeme, +zda $\alpha a$ je stále vnořený suffix. Pokud ano, nic se nemění, pokud ne, přidáme nový list +a případně také vnitřní vrchol, $\alpha$ zkrátíme zleva o~znak a testujeme dál. -\s{Analýza:} Po~pøidání jednoho znaku na konec slova~$\sigma$ provedeme amortizovanì -konstantní poèet úprav stromu (ka¾dá úprava slovo $\alpha$ zkrátí, po v¹ech úpravách -pøidáme k~$\alpha$ jediný znak). Tudí¾ staèí ukázat, jak provést ka¾dou úpravu -v~(amortizovanì) konstantním èase. K~tomu potøebujeme ¹ikovnou reprezentaci slova~$\alpha$, -která bude umìt efektivnì prodlu¾ovat zprava, zkracovat zleva a testovat existenci +\s{Analýza:} Po~přidání jednoho znaku na konec slova~$\sigma$ provedeme amortizovaně +konstantní počet úprav stromu (každá úprava slovo $\alpha$ zkrátí, po vÅ¡ech úpravách +přidáme k~$\alpha$ jediný znak). Tudíž stačí ukázat, jak provést každou úpravu +v~(amortizovaně) konstantním čase. K~tomu potřebujeme Å¡ikovnou reprezentaci slova~$\alpha$, +která bude umět efektivně prodlužovat zprava, zkracovat zleva a testovat existenci vrcholu ve~stromu. -\s{Definice:} {\I Referenèní pár} pro slovo $\alpha\subseteq\sigma$ je dvojice -$(\pi,\tau)$, v~ní¾ $\pi$ je vrchol stromu, $\tau$ libovolné slovo a $\pi\tau=\alpha$. -Navíc víme, ¾e $\tau\subseteq\sigma$, tak¾e si~$\tau$ staèí pamatovat jako dvojici -indexù ve~slovì~$\sigma$. +\s{Definice:} {\I Referenční pár} pro slovo $\alpha\subseteq\sigma$ je dvojice +$(\pi,\tau)$, v~níž $\pi$ je vrchol stromu, $\tau$ libovolné slovo a $\pi\tau=\alpha$. +Navíc víme, že $\tau\subseteq\sigma$, takže si~$\tau$ stačí pamatovat jako dvojici +indexů ve~slově~$\sigma$. -Referenèní pár je {\I kanonický,} pokud neexistuje hrana vedoucí z~vrcholu~$\pi$ s~nálepkou, -která by byla prefixem slova~$\tau$. (V¹imnìte si, ¾e taková hrana se pozná podle toho, -¾e první znak nálepky se shoduje s~prvním znakem slova~$\tau$ a nálepka není del¹í ne¾ -slovo~$\tau$. Shodu ostatních znakù není nutné kontrolovat.) +Referenční pár je {\I kanonický,} pokud neexistuje hrana vedoucí z~vrcholu~$\pi$ s~nálepkou, +která by byla prefixem slova~$\tau$. (VÅ¡imněte si, že taková hrana se pozná podle toho, +že první znak nálepky se shoduje s~prvním znakem slova~$\tau$ a nálepka není delší než +slovo~$\tau$. Shodu ostatních znaků není nutné kontrolovat.) -\s{Pozorování:} Ke~ka¾dému slovu $\alpha\subseteq\sigma$ existuje právì jeden kanonický -referenèní pár, který ho popisuje. To je ze~v¹ech referenèních párù pro toto slovo -ten s~nejdel¹ím~$\pi$ (nejhlub¹ím vrcholem). +\s{Pozorování:} Ke~každému slovu $\alpha\subseteq\sigma$ existuje právě jeden kanonický +referenční pár, který ho popisuje. To je ze~vÅ¡ech referenčních párů pro toto slovo +ten s~nejdelším~$\pi$ (nejhlubším vrcholem). -\s{Definice:} Zpìtná hrana $\(\pi)$ vede z~vrcholu $\pi$ do~vrcholu, -který je zkrácením slova~$\pi$ o~jeden znak zleva. (Nahlédneme, ¾e takový -vrchol musí existovat: pokud je $\pi$ vnitøní vrchol, pak je slovo~$\pi$ -vìtvící, tak¾e ka¾dý jeho suffix musí také být vìtvící, a~tím pádem musí -odpovídat nìjakého vrcholu.) +\s{Definice:} Zpětná hrana $\(\pi)$ vede z~vrcholu $\pi$ do~vrcholu, +který je zkrácením slova~$\pi$ o~jeden znak zleva. (Nahlédneme, že takový +vrchol musí existovat: pokud je $\pi$ vnitřní vrchol, pak je slovo~$\pi$ +větvící, takže každý jeho suffix musí také být větvící, a~tím pádem musí +odpovídat nějakého vrcholu.) -\s{Operace s~referenèními páry:} -S~referenèním párem $(\pi,\tau)$ popisujícím slovo~$\alpha$ potøebujeme provádìt -následujicí operace: +\s{Operace s~referenčními páry:} +S~referenčním párem $(\pi,\tau)$ popisujícím slovo~$\alpha$ potřebujeme provádět +následujicí operace: \itemize\ibull -\:{\I Pøidání znaku~$a$ na konec:} Pøipí¹eme~$a$ na konec slova~$\tau$. - To je jistì referenèní pár pro $\alpha a$, ale nemusí být kanonický. - Pøitom mù¾eme snadno ovìøit, zda se $\alpha a$ ve~stromu nachází, - a pøípadnì operaci odmítnout. -\:{\I Odebrání znaku ze~zaèátku:} Pokud $\pi$ není koøen stromu, polo¾íme - $\pi\leftarrow\(\pi)$ a zachováme~$\tau$. Pokud naopak je~$\pi$ - prázdný øetìzec, odebereme z~$\tau$ jeho první znak (to lze udìlat - v~konstantním èase, proto¾e~$\tau$ je reprezentované dvojicí indexù do~$\sigma$). -\:{\I Pøevedení na kanonický tvar:} Obì pøedchozí operace mohou vytvoøit referenèní - pár, který není kanonický. Poka¾dé proto kanonicitu zkontrolujeme a pøípadnì - pár upravíme. Ovìøíme, zda hrana z~$\pi$ indexovaná písmenem~$a$ není - dost krátká na to, aby byla prefixem slova~$\tau$. Pokud je, tak se - po~této hranì pøesuneme dolù, èím¾~$\pi$ prodlou¾íme a~$\tau$ zkrátíme, - a proces opakujeme. Jeliko¾ tím poka¾dé $\tau$~zkrátíme a kdykoliv jindy - se $\tau$ prodlou¾í nejvý¹e o~1, mají v¹echny pøevody na kanonický tvar - amortizovanì konstantní slo¾itost. +\:{\I Přidání znaku~$a$ na konec:} Připíšeme~$a$ na konec slova~$\tau$. + To je jistě referenční pár pro $\alpha a$, ale nemusí být kanonický. + Přitom můžeme snadno ověřit, zda se $\alpha a$ ve~stromu nachází, + a případně operaci odmítnout. +\:{\I Odebrání znaku ze~začátku:} Pokud $\pi$ není kořen stromu, položíme + $\pi\leftarrow\(\pi)$ a zachováme~$\tau$. Pokud naopak je~$\pi$ + prázdný řetězec, odebereme z~$\tau$ jeho první znak (to lze udělat + v~konstantním čase, protože~$\tau$ je reprezentované dvojicí indexů do~$\sigma$). +\:{\I Převedení na kanonický tvar:} Obě předchozí operace mohou vytvořit referenční + pár, který není kanonický. Pokaždé proto kanonicitu zkontrolujeme a případně + pár upravíme. Ověříme, zda hrana z~$\pi$ indexovaná písmenem~$a$ není + dost krátká na to, aby byla prefixem slova~$\tau$. Pokud je, tak se + po~této hraně přesuneme dolů, čímž~$\pi$ prodloužíme a~$\tau$ zkrátíme, + a proces opakujeme. Jelikož tím pokaždé $\tau$~zkrátíme a kdykoliv jindy + se $\tau$ prodlouží nejvýše o~1, mají vÅ¡echny převody na kanonický tvar + amortizovaně konstantní složitost. \endlist -\>Nyní ji¾ mù¾eme doplnit detaily, získat celý algoritmus a nahlédnout, -¾e pracuje v~amortizovanì konstantním èase. +\>Nyní již můžeme doplnit detaily, získat celý algoritmus a nahlédnout, +že pracuje v~amortizovaně konstantním čase. -\s{Algoritmus podrobnìji:} +\s{Algoritmus podrobněji:} \algo -\:{\I Vstup:} $\alpha=\alpha(\sigma)$ reprezentovaný jako kanonický referenèní pár $(\pi,\tau)$, $T$ suffixový strom pro~$\sigma$ spolu s~hranami \, nový znak~$a$. -\:Zjistíme, jestli $\alpha a$ je pøítomen ve~stromu, a pøípadnì ho zalo¾íme: -\::Pokud $\tau=\varepsilon$: ($\alpha=\pi$ je vnitøní vrchol) -\:::Vede-li z~vrcholu $\pi$ hrana s~nálepkou zaèínající znakem $a$, pak je pøítomen. -\:::Nevede-li, není pøítomen, a~tak pøidáme novou otevøenou hranu vedoucí z~$\pi$ do~nového listu. -\::Pokud $\tau\ne\varepsilon$: ($\alpha$ je skrytý vrchol) -\:::Najdeme hranu, po~ní¾ z~$\pi$ pokraèuje slovo $\tau$ (která to je, poznáme podle prvního znaku slova~$\tau$). -\:::Pokud v~popisce této hrany po~$\tau$ následuje znak~$a$, pak je $\alpha a$ pøítomen. -\:::Pokud nenásleduje, tak nebyl pøítomen, èili tuto hranu rozdìlíme: pøidáme na~ni nový vnitøní vrchol, - do~nìj¾ povede hrana s~popiskou~$\tau$ a z~nìj zbytek pùvodní hrany a otevøená hrana do~nového listu. -\:Pokud $\alpha a$ nebyl pøítomen, tak $\alpha$ zkrátíme a vrátíme se na~krok~2. -\:Nyní víme, ¾e $\alpha a$ ji¾ byl pøítomen, tak¾e upravíme referenèní pár, aby popisoval $\alpha a$. -\:Dopoèítáme zpìtné hrany (viz ní¾e). -\:{\I Výstup:} $\alpha=\alpha(\sigma a)$ jako kanonický referenèní pár $(\pi,\tau)$, $T$ suffixový strom pro~$\sigma a$ - a jeho zpìtné hrany \. +\:{\I Vstup:} $\alpha=\alpha(\sigma)$ reprezentovaný jako kanonický referenční pár $(\pi,\tau)$, $T$ suffixový strom pro~$\sigma$ spolu s~hranami \, nový znak~$a$. +\:Zjistíme, jestli $\alpha a$ je přítomen ve~stromu, a případně ho založíme: +\::Pokud $\tau=\varepsilon$: ($\alpha=\pi$ je vnitřní vrchol) +\:::Vede-li z~vrcholu $\pi$ hrana s~nálepkou začínající znakem $a$, pak je přítomen. +\:::Nevede-li, není přítomen, a~tak přidáme novou otevřenou hranu vedoucí z~$\pi$ do~nového listu. +\::Pokud $\tau\ne\varepsilon$: ($\alpha$ je skrytý vrchol) +\:::Najdeme hranu, po~níž z~$\pi$ pokračuje slovo $\tau$ (která to je, poznáme podle prvního znaku slova~$\tau$). +\:::Pokud v~popisce této hrany po~$\tau$ následuje znak~$a$, pak je $\alpha a$ přítomen. +\:::Pokud nenásleduje, tak nebyl přítomen, čili tuto hranu rozdělíme: přidáme na~ni nový vnitřní vrchol, + do~nějž povede hrana s~popiskou~$\tau$ a z~něj zbytek původní hrany a otevřená hrana do~nového listu. +\:Pokud $\alpha a$ nebyl přítomen, tak $\alpha$ zkrátíme a vrátíme se na~krok~2. +\:Nyní víme, že $\alpha a$ již byl přítomen, takže upravíme referenční pár, aby popisoval $\alpha a$. +\:Dopočítáme zpětné hrany (viz níže). +\:{\I Výstup:} $\alpha=\alpha(\sigma a)$ jako kanonický referenční pár $(\pi,\tau)$, $T$ suffixový strom pro~$\sigma a$ + a jeho zpětné hrany \. \endalgo -\s{Zpìtné hrany:} -Zbývá dodat, jak nastavovat novým vrcholùm jejich zpìtné hrany. To potøebujeme -jen pro vnitøní vrcholy (na~zpìtné hrany z~listù se algoritmus nikdy neodkazuje). -V¹imneme si, ¾e pokud jsme zalo¾ili vrchol, odpovídá tento vrchol v¾dy souèasnému~$\alpha$ -a zpìtná hrana z~nìj povede do~zkrácení slova~$\alpha$ o~znak zleva, co¾ je -pøesnì vrchol, který zalo¾íme (nebo zjistíme, ¾e u¾ existuje) v~pøí¹tí iteraci -hlavního cyklu. V~dal¹í iteraci je¹tì urèitì nebudeme tuto hranu potøebovat, -proto¾e $\pi$ v¾dy jen zkracujeme, a~tak mù¾eme vznik zpìtné hrany o~iteraci -zpozdit. Výroba zpìtné hrany tedy bude také trvat jen konstantnì dlouho. +\s{Zpětné hrany:} +Zbývá dodat, jak nastavovat novým vrcholům jejich zpětné hrany. To potřebujeme +jen pro vnitřní vrcholy (na~zpětné hrany z~listů se algoritmus nikdy neodkazuje). +VÅ¡imneme si, že pokud jsme založili vrchol, odpovídá tento vrchol vždy současnému~$\alpha$ +a zpětná hrana z~něj povede do~zkrácení slova~$\alpha$ o~znak zleva, což je +přesně vrchol, který založíme (nebo zjistíme, že už existuje) v~příští iteraci +hlavního cyklu. V~další iteraci jeÅ¡tě určitě nebudeme tuto hranu potřebovat, +protože $\pi$ vždy jen zkracujeme, a~tak můžeme vznik zpětné hrany o~iteraci +zpozdit. Výroba zpětné hrany tedy bude také trvat jen konstantně dlouho. \references \bye diff --git a/11-planar/11-planar.tex b/11-planar/11-planar.tex index a52fd02..66d9a4a 100644 --- a/11-planar/11-planar.tex +++ b/11-planar/11-planar.tex @@ -1,340 +1,340 @@ \input ../sgr.tex -\prednaska{11}{Kreslení grafù do roviny}{} - -Rovinné grafy se objevují v~nejrùznìj¹ích praktických aplikacích teorie grafù, -a~tak okolo nich vyrostlo znaèné mno¾ství algoritmù. I~kdy¾ existují výjimky, -jako napøíklad ji¾ zmínìné hledání kostry rovinného grafu, vìt¹ina takových -algoritmù pracuje s~konkrétním vnoøením grafu do~roviny (rovinným nakreslením). - -Proto se zamìøíme na~algoritmus, který zadaný graf buïto vnoøí do~roviny, nebo se -zastaví s~tím, ¾e graf není rovinný. Tarjan ji¾ v~roce 1974 ukázal \cite{tarjan:planarity}, -¾e je to mo¾né provést v~lineárním èase, ale jeho algoritmus je ponìkud -komplikovaný. Od~té doby se objevilo mnoho zjednodu¹ení, prozatím vrcholících -algoritmem Boyera a Myrvoldové \cite{boyer:cutting}, a ten zde uká¾eme. - -Zmiòme je¹tì, ¾e existují i algoritmy, které vytváøejí rovinná nakreslení s~rùznými -speciálními vlastnostmi. Je to napøíklad Schnyderùv algoritmus~\cite{schnyder:grid} -generující v~lineárním èase nakreslení, v~nìm¾ jsou hrany úseèkami a vrcholy -le¾í v~møí¾ových bodech møí¾ky $(n-2)\times (n-2)$, a~o~nìco jednodu¹¹í algoritmus -Chrobaka a Payneho \cite{chrobak:grid} kreslící do~møí¾ky $(2n-4)\times (n-2)$. -Oba ov¹em pracují tak, ¾e vyjdou z~obyèejného rovinného nakreslení a upravují ho, -aby splòovalo dodateèné podmínky. +\prednaska{11}{Kreslení grafů do roviny}{} + +Rovinné grafy se objevují v~nejrůznějších praktických aplikacích teorie grafů, +a~tak okolo nich vyrostlo značné množství algoritmů. I~když existují výjimky, +jako například již zmíněné hledání kostry rovinného grafu, větÅ¡ina takových +algoritmů pracuje s~konkrétním vnořením grafu do~roviny (rovinným nakreslením). + +Proto se zaměříme na~algoritmus, který zadaný graf buďto vnoří do~roviny, nebo se +zastaví s~tím, že graf není rovinný. Tarjan již v~roce 1974 ukázal \cite{tarjan:planarity}, +že je to možné provést v~lineárním čase, ale jeho algoritmus je poněkud +komplikovaný. Od~té doby se objevilo mnoho zjednoduÅ¡ení, prozatím vrcholících +algoritmem Boyera a Myrvoldové \cite{boyer:cutting}, a ten zde ukážeme. + +Zmiňme jeÅ¡tě, že existují i algoritmy, které vytvářejí rovinná nakreslení s~různými +speciálními vlastnostmi. Je to například Schnyderův algoritmus~\cite{schnyder:grid} +generující v~lineárním čase nakreslení, v~němž jsou hrany úsečkami a vrcholy +leží v~mřížových bodech mřížky $(n-2)\times (n-2)$, a~o~něco jednodušší algoritmus +Chrobaka a Payneho \cite{chrobak:grid} kreslící do~mřížky $(2n-4)\times (n-2)$. +Oba ovÅ¡em pracují tak, že vyjdou z~obyčejného rovinného nakreslení a upravují ho, +aby splňovalo dodatečné podmínky. \h{DFS a bloky} -Pøipomeòme si nejprve nìkteré vlastnosti prohledávání do~hloubky (DFS) a jeho pou¾ití -k~hledání komponent vrcholové 2-souvislosti {\I (blokù).} +Připomeňme si nejprve některé vlastnosti prohledávání do~hloubky (DFS) a jeho použití +k~hledání komponent vrcholové 2-souvislosti {\I (bloků).} -\s{Definice:} Prohledávání orientovaného grafu do~hloubky rozdìlí hrany do~ètyø druhù: +\s{Definice:} Prohledávání orientovaného grafu do~hloubky rozdělí hrany do~čtyř druhů: \itemize\ibull -\:{\I stromové} -- po~nich DFS pro¹lo a rekurzivnì se zavolalo; tyto hrany -vytváøejí {\I DFS strom} orientovaný z~koøene; -\:{\I zpìtné} -- vedou do~vrcholu, který le¾í na cestì z~koøene DFS stromu -do právì prohledávaného vrcholu; jinými slovy vedou do vrcholu, který se -právì nachází na~zásobníku; -\:{\I dopøedné} -- vedou do~ji¾ zpracovaného vrcholu le¾ícího v~DFS stromu pod aktuálním vrcholem; -\:{\I pøíèné} -- zbývající hrany, které vedou do vrcholu ji¾ zpracovaného vrcholu -v~jiném podstromu. +\:{\I stromové} -- po~nich DFS proÅ¡lo a rekurzivně se zavolalo; tyto hrany +vytvářejí {\I DFS strom} orientovaný z~kořene; +\:{\I zpětné} -- vedou do~vrcholu, který leží na cestě z~kořene DFS stromu +do právě prohledávaného vrcholu; jinými slovy vedou do vrcholu, který se +právě nachází na~zásobníku; +\:{\I dopředné} -- vedou do~již zpracovaného vrcholu ležícího v~DFS stromu pod aktuálním vrcholem; +\:{\I příčné} -- zbývající hrany, které vedou do vrcholu již zpracovaného vrcholu +v~jiném podstromu. \endlist -\s{Pozorování:} -Pokud DFS spustíme na neorientovaný graf a hranu, po~ní¾ jsme u¾ jednou pro¹li, -v~opaèném smìru ignorujeme, existují pouze stromové a zpìtné hrany. DFS strom -tvoøí kostru grafu. +\s{Pozorování:} +Pokud DFS spustíme na neorientovaný graf a hranu, po~níž jsme už jednou proÅ¡li, +v~opačném směru ignorujeme, existují pouze stromové a zpětné hrany. DFS strom +tvoří kostru grafu. -Nyní u¾ se zamìøíme pouze na~neorientované grafy~\dots +Nyní už se zaměříme pouze na~neorientované grafy~\dots -\s{Lemma:} Relace \uv{Hrany $e$ a $f$ le¾í na~spoleèné kru¾nici} (znaèíme $e\sim f$) je ekvivalence. Její -tøídy tvoøí maximální 2-souvislé podgrafy (bloky); ekvivalenèní tøídy s~jedinou hranou (mosty) pova¾ujeme -za triviální bloky. Vrchol $v$ je artikulace právì tehdy, sousedí-li s~ním hrany z~více blokù. +\s{Lemma:} Relace \uv{Hrany $e$ a $f$ leží na~společné kružnici} (značíme $e\sim f$) je ekvivalence. Její +třídy tvoří maximální 2-souvislé podgrafy (bloky); ekvivalenční třídy s~jedinou hranou (mosty) považujeme +za triviální bloky. Vrchol $v$ je artikulace právě tehdy, sousedí-li s~ním hrany z~více bloků. -Pokud spustíme na~graf DFS, je pøirozené testovat, do~jakých blokù patøí stromové -hrany sousedící s~právì prohledávaným vrcholem~$v$: stromová hrana $uv$, po~které jsme -do~$v$ pøi¹li, a hrany $vw_1$ a¾ $vw_k$ vedoucí do~podstromù $T_1$ a¾ $T_k$ (zpìtné hrany -jsou v¾dy ekvivalentní s~hranou $uv$). Pokud je $uv \sim vw_i$, musí existovat cesta -z~podstromu $T_i$ do~vrcholu~$u$, která nepou¾ije právì testované hrany. Taková cesta -ale mù¾e podstrom opustit pouze zpìtnou hranou (stromová je zakázaná a dopøedné ani pøíèné -neexistují). Jinými slovy $uv\sim vw_i$ právì tehdy, kdy¾ existuje zpìtná hrana z~podstromu~$T_i$ -do~vrcholu $u$ nebo blí¾e ke~koøeni. +Pokud spustíme na~graf DFS, je přirozené testovat, do~jakých bloků patří stromové +hrany sousedící s~právě prohledávaným vrcholem~$v$: stromová hrana $uv$, po~které jsme +do~$v$ přiÅ¡li, a hrany $vw_1$ až $vw_k$ vedoucí do~podstromů $T_1$ až $T_k$ (zpětné hrany +jsou vždy ekvivalentní s~hranou $uv$). Pokud je $uv \sim vw_i$, musí existovat cesta +z~podstromu $T_i$ do~vrcholu~$u$, která nepoužije právě testované hrany. Taková cesta +ale může podstrom opustit pouze zpětnou hranou (stromová je zakázaná a dopředné ani příčné +neexistují). Jinými slovy $uv\sim vw_i$ právě tehdy, když existuje zpětná hrana z~podstromu~$T_i$ +do~vrcholu $u$ nebo blíže ke~kořeni. -Pokud nìkterá dvojice $vw_i$, $vw_j$ není ekvivalentní pøes hranu $uv$ (nebo pokud hrana $uv$ -ani neexistuje, co¾ se nám v~koøeni DFS stromu mù¾e stát), le¾í tyto hrany v~rùzných blocích, proto¾e -$T_i$ a $T_j$ mohou být spojeny jen pøes své koøeny (pøíèné hrany neexistují). Ze~zpìtných -hran tedy získáme kompletní strukturu blokù. +Pokud některá dvojice $vw_i$, $vw_j$ není ekvivalentní přes hranu $uv$ (nebo pokud hrana $uv$ +ani neexistuje, což se nám v~kořeni DFS stromu může stát), leží tyto hrany v~různých blocích, protože +$T_i$ a $T_j$ mohou být spojeny jen přes své kořeny (příčné hrany neexistují). Ze~zpětných +hran tedy získáme kompletní strukturu bloků. -Nyní si staèí rozmyslet, jak existenci zpìtných hran testovat rychle. K~tomu se bude hodit: +Nyní si stačí rozmyslet, jak existenci zpětných hran testovat rychle. K~tomu se bude hodit: \s{Definice:} Je-li $v$ vrchol grafu, pak: \itemize\ibull -\:$\(v)$ udává poøadí, v~nìm¾ DFS do~vrcholu~$v$ vstoupilo. -\:$\(v)$ je nejmen¹í z~\ù vrcholù, do~nich¾ vede z~$v$ zpìtná hrana, -nebo $+\infty$, pokud z~$v$ ¾ádná zpìtná hrana nevede. -\:$\(v)$ je minimum z~\ù vrcholù le¾ících v~podstromu pod~$v$, vèetnì $v$ samého. +\:$\(v)$ udává pořadí, v~němž DFS do~vrcholu~$v$ vstoupilo. +\:$\(v)$ je nejmenší z~\ů vrcholů, do~nichž vede z~$v$ zpětná hrana, +nebo $+\infty$, pokud z~$v$ žádná zpětná hrana nevede. +\:$\(v)$ je minimum z~\ů vrcholů ležících v~podstromu pod~$v$, včetně $v$ samého. \endlist -\s{Pozorování:} \, \ i \ v¹ech vrcholù lze spoèítat -bìhem prohledávání, tedy také v~lineárním èase. +\s{Pozorování:} \, \ i \ vÅ¡ech vrcholů lze spočítat +během prohledávání, tedy také v~lineárním čase. -Rozpoznávání blokù a artikulací mù¾eme shrnout do~následujícího lemmatu: +Rozpoznávání bloků a artikulací můžeme shrnout do~následujícího lemmatu: \s{Lemma:} Pokud $v$ je vrchol grafu, $u$ jeho otec a $w$ jeho syn v~DFS stromu, -pak stromové hrany $uv$ a $vw$ le¾í v~tomté¾ bloku ($uv\sim vw$) právì -tehdy, kdy¾ $\(w) < \(v)$, a~$v$ je artikulace právì kdy¾ -nìkterý z~jeho synù $w$ má $\(w) \ge \(v)$. -Koøen DFS stromu je artikulace, právì kdy¾ má více ne¾ jednoho syna. - -\h{Postup kreslení} - -Graf budeme kreslit v~opaèném poøadí oproti DFS, tj. od~nejvìt¹ích \ù k~nejmen¹ím, -a v¾dy si budeme udr¾ovat blokovou strukturu ji¾ nakreslené èásti grafu, uspoøádanou -podle DFS stromu -- ka¾dý blok bude mít svùj koøen, s~výjimkou nejvy¹¹ího bloku -je tento koøen souèasnì artikulací v~nadøazeném bloku. Aby se nám tato situace snadno -reprezentovala, artikulace naklonujeme a ka¾dý blok dostane svou vlastní kopii artikulace. - -Také budeme vyu¾ívat toho, ¾e nakreslení ka¾dého bloku, který není -most, je ohranièeno kru¾nicí, a mosty zdvojíme, aby to pro nì platilo -také. Navíc v~libovolném nakreslení mù¾eme kterýkoliv blok spolu se v¹emi bloky -le¾ícími pod~ním pøeklopit podle koøenové artikulace, ani¾ bychom poru¹ili +pak stromové hrany $uv$ a $vw$ leží v~tomtéž bloku ($uv\sim vw$) právě +tehdy, když $\(w) < \(v)$, a~$v$ je artikulace právě když +některý z~jeho synů $w$ má $\(w) \ge \(v)$. +Kořen DFS stromu je artikulace, právě když má více než jednoho syna. + +\h{Postup kreslení} + +Graf budeme kreslit v~opačném pořadí oproti DFS, tj. od~největších \ů k~nejmenším, +a vždy si budeme udržovat blokovou strukturu již nakreslené části grafu, uspořádanou +podle DFS stromu -- každý blok bude mít svůj kořen, s~výjimkou nejvyššího bloku +je tento kořen současně artikulací v~nadřazeném bloku. Aby se nám tato situace snadno +reprezentovala, artikulace naklonujeme a každý blok dostane svou vlastní kopii artikulace. + +Také budeme využívat toho, že nakreslení každého bloku, který není +most, je ohraničeno kružnicí, a mosty zdvojíme, aby to pro ně platilo +také. Navíc v~libovolném nakreslení můžeme kterýkoliv blok spolu se vÅ¡emi bloky +ležícími pod~ním překlopit podle kořenové artikulace, aniž bychom poruÅ¡ili rovinnost. \finalfix{ \smallskip -\figure{planar1.eps}{Pøed nakreslením zpìtných hran \dots}{\epsfxsize} -\figure{planar2.eps}{\dots\ po nìm (ètvereèky jsou externí vrcholy)}{\epsfxsize} +\figure{planar1.eps}{Před nakreslením zpětných hran \dots}{\epsfxsize} +\figure{planar2.eps}{\dots\ po něm (čtverečky jsou externí vrcholy)}{\epsfxsize} } -V¹imnìme si, ¾e pokud vede z~nìjakého u¾ nakresleného vrcholu je¹tì nenakreslená hrana, -lze pokraèovat po~nenakreslených hranách a¾ do~koøene DFS stromu. V¹echny vrcholy, ke~kterým -je¹tì bude potøeba nìco pøipojit (takovým budeme øíkat {\I externí} a hranám -rovnì¾; za~chvíli to nadefinujeme formálnì), proto musí le¾et v~té¾e stìnì dosud nakresleného -podgrafu a bez újmy na~obecnosti si vybereme, ¾e to bude vnìj¹í stìna. - -Základním krokem algoritmu tedy bude roz¹íøit nakreslení o~nový -vrchol~$v$ a o~v¹echny hrany vedoucí z~nìj do~jeho (ji¾ nakreslených) -DFS-následníkù. Stromové hrany pùjdou nakreslit v¾dy, pøidáme je jako -triviální bloky (2-cykly) a nejsou-li to mosty, brzy se nìjakou -zpìtnou hranou spojí s~jinými bloky. Zpìtné hrany byly a¾ donedávna -externí, tak¾e pøidání jedné zpìtné hrany nahradí cestu -po~okraji bloku touto hranou (tím vytvoøí novou stìnu) a také mù¾e -slouèit nìkolik blokù do~jednoho, jak je vidìt z~obrázkù. +VÅ¡imněme si, že pokud vede z~nějakého už nakresleného vrcholu jeÅ¡tě nenakreslená hrana, +lze pokračovat po~nenakreslených hranách až do~kořene DFS stromu. VÅ¡echny vrcholy, ke~kterým +jeÅ¡tě bude potřeba něco připojit (takovým budeme říkat {\I externí} a hranám +rovněž; za~chvíli to nadefinujeme formálně), proto musí ležet v~téže stěně dosud nakresleného +podgrafu a bez újmy na~obecnosti si vybereme, že to bude vnější stěna. + +Základním krokem algoritmu tedy bude rozšířit nakreslení o~nový +vrchol~$v$ a o~vÅ¡echny hrany vedoucí z~něj do~jeho (již nakreslených) +DFS-následníků. Stromové hrany půjdou nakreslit vždy, přidáme je jako +triviální bloky (2-cykly) a nejsou-li to mosty, brzy se nějakou +zpětnou hranou spojí s~jinými bloky. Zpětné hrany byly až donedávna +externí, takže přidání jedné zpětné hrany nahradí cestu +po~okraji bloku touto hranou (tím vytvoří novou stěnu) a také může +sloučit několik bloků do~jednoho, jak je vidět z~obrázků. \separatefix{ -\figure{planar1.eps}{Pøed nakreslením zpìtných hran \dots}{\epsfxsize} -\figure{planar2.eps}{\dots\ po nìm (ètvereèky jsou externí vrcholy)}{\epsfxsize} +\figure{planar1.eps}{Před nakreslením zpětných hran \dots}{\epsfxsize} +\figure{planar2.eps}{\dots\ po něm (čtverečky jsou externí vrcholy)}{\epsfxsize} } -Bude se nám hodit, ¾e èas potøebný na~tuto operaci je pøímo úmìrný poètu -hran, které ubyly z~vnìj¹í stìny, co¾ je amortizovanì konstanta. - -Mù¾e se nám ale také stát, ¾e zpìtná hrana zakryje nìjaký externí vrchol. -Tehdy musíme nìkteré bloky pøeklopit tak, aby externí vrcholy -zùstaly venku. Potøebujeme tedy datové struktury, pomocí nich¾ bude mo¾né -pøeklápìt efektivnì a co víc, také rychle poznávat, kdy je pøeklápìní potøebné. - -\h{Externí vrcholy} - -Jestli¾e z~nìjakého vrcholu~$v$ bloku~$B$ vede dosud nenakreslená hrana, musí -být tento vrchol na~vnìj¹í stìnì, tak¾e musí také zùstat na~vnìj¹í stìnì -i~vrchol, pøes který je~$B$ pøipojen ke~zbytku grafu. Proto externost -nadefinujeme tak, aby pokrývala i tyto pøípady: - -\s{Definice:} Vrchol~$w$ je {\I externí,} pokud buïto z~$w$ vede zpìtná -hrana do~je¹tì nenakresleného vrcholu, nebo je pod~$w$ pøipojen externí -blok, èili blok obsahující alespoò jeden externí vrchol. Ostatním vrcholùm -budeme øíkat {\I interní.} - -Jinými slovy platí, ¾e vrchol $w$ je externí pøi zpracování vrcholu~$v$, pakli¾e $\(w) < \(v)$, -nebo pokud pro nìkterého ze~synù $x$ le¾ícího v~jiném bloku je $\(x) < \(v)$. -Druhá podmínka funguje díky tomu, ¾e koøen bloku má v~tomto bloku právì jednoho syna -(jinak by existovala pøíèná hrana, co¾ víme, ¾e není pravda), tak¾e minimum z~\ù -v¹ech vrcholù le¾ících uvnitø bloku je pøesnì \ tohoto syna. -Ve~statickém grafu by se v¹echny testy redukovaly na~$\(w)$, nám se ov¹em bloková -struktura prùbì¾nì mìní, tak¾e musíme uva¾ovat bloky v~souèasném okam¾iku. Proto si zavedeme: - -\s{Definice:} $\(w)$ je seznam v¹ech blokù pøipojených v~daném okam¾iku -pod vrcholem~$w$, reprezentovaných jejich koøeny (klony vrcholu~$w$) a jedinými syny koøenù. -Tento seznam udr¾ujeme setøídìný vzestupnì podle $\$ù synù. - -\s{Lemma:} Vrchol~$w$ je externí pøi zpracování vrcholu~$v$, pokud je buïto $\(w) < \(v)$, -nebo první prvek seznamu $\(w)$ má $\ < \(v)$. Navíc -seznamy \ lze udr¾ovat v~amortizovanì konstantním èase. - -\proof První èást plyne pøímo z~definic. V¹echny seznamy na~zaèátku bìhu algoritmu -sestrojíme v~lineárním èase pøihrádkovým tøídìním a kdykoliv slouèíme blok -s~nadøazeným blokem, odstraníme ho ze~seznamu v~pøíslu¹né artikulaci. +Bude se nám hodit, že čas potřebný na~tuto operaci je přímo úměrný počtu +hran, které ubyly z~vnější stěny, což je amortizovaně konstanta. + +Může se nám ale také stát, že zpětná hrana zakryje nějaký externí vrchol. +Tehdy musíme některé bloky překlopit tak, aby externí vrcholy +zůstaly venku. Potřebujeme tedy datové struktury, pomocí nichž bude možné +překlápět efektivně a co víc, také rychle poznávat, kdy je překlápění potřebné. + +\h{Externí vrcholy} + +Jestliže z~nějakého vrcholu~$v$ bloku~$B$ vede dosud nenakreslená hrana, musí +být tento vrchol na~vnější stěně, takže musí také zůstat na~vnější stěně +i~vrchol, přes který je~$B$ připojen ke~zbytku grafu. Proto externost +nadefinujeme tak, aby pokrývala i tyto případy: + +\s{Definice:} Vrchol~$w$ je {\I externí,} pokud buďto z~$w$ vede zpětná +hrana do~jeÅ¡tě nenakresleného vrcholu, nebo je pod~$w$ připojen externí +blok, čili blok obsahující alespoň jeden externí vrchol. Ostatním vrcholům +budeme říkat {\I interní.} + +Jinými slovy platí, že vrchol $w$ je externí při zpracování vrcholu~$v$, pakliže $\(w) < \(v)$, +nebo pokud pro některého ze~synů $x$ ležícího v~jiném bloku je $\(x) < \(v)$. +Druhá podmínka funguje díky tomu, že kořen bloku má v~tomto bloku právě jednoho syna +(jinak by existovala příčná hrana, což víme, že není pravda), takže minimum z~\ů +vÅ¡ech vrcholů ležících uvnitř bloku je přesně \ tohoto syna. +Ve~statickém grafu by se vÅ¡echny testy redukovaly na~$\(w)$, nám se ovÅ¡em bloková +struktura průběžně mění, takže musíme uvažovat bloky v~současném okamžiku. Proto si zavedeme: + +\s{Definice:} $\(w)$ je seznam vÅ¡ech bloků připojených v~daném okamžiku +pod vrcholem~$w$, reprezentovaných jejich kořeny (klony vrcholu~$w$) a jedinými syny kořenů. +Tento seznam udržujeme setříděný vzestupně podle $\$ů synů. + +\s{Lemma:} Vrchol~$w$ je externí při zpracování vrcholu~$v$, pokud je buďto $\(w) < \(v)$, +nebo první prvek seznamu $\(w)$ má $\ < \(v)$. Navíc +seznamy \ lze udržovat v~amortizovaně konstantním čase. + +\proof První část plyne přímo z~definic. VÅ¡echny seznamy na~začátku běhu algoritmu +sestrojíme v~lineárním čase přihrádkovým tříděním a kdykoliv sloučíme blok +s~nadřazeným blokem, odstraníme ho ze~seznamu v~přísluÅ¡né artikulaci. \qed -\h{Reprezentace blokù a pøeklápìní} - -Pro ka¾dý blok si potøebujeme pamatovat vrcholy, které le¾í na~hranici -(nìkteré z~nich jsou externí, ale to u¾ umíme poznat) a bloky, -které jsou pod nimi pøipojené. Dále je¹tì vnitøní strukturu bloku vèetnì -uvnitø pøipojených dal¹ích blokù, ale jeliko¾ ¾ádné vnitøní vrcholy nejsou -externí, vnitøek u¾ neovlivní dal¹í výpoèet a potøebujeme jej pouze -pro vypsání výstupu. - -Pro na¹e úèely bude staèit zapamatovat si u~ka¾dého bloku, jestli je -oproti nadøazenému bloku pøeklopen. Tuto informaci zapí¹eme do~koøene -bloku. Ka¾dý vrchol na~hranici bloku pak bude obsahovat dva~ukazatele -na~sousední vrcholy. Neumíme sice lokálnì poznat, který ukazatel odpovídá -kterému smìru, ale kdy¾ se nìjakým smìrem vydáme, doká¾eme ho dodr¾et --- staèí si v¾dy vybrat ten ukazatel, který nás nezavede do~právì -opu¹tìného vrcholu. - -Ka¾dý vrchol si také bude pamatovat seznam svých sousedù, -podle orientace bloku buïto v~hodinkovém nebo opaèném poøadí. -Chceme-li pøidat hranu, potøebujeme tedy znát absolutní orientaci, -ale to pùjde snadno, jeliko¾ hrany pøidáváme jen k~vrcholùm na~hranici, -poté co k~nim po~hranici dojdeme z~koøene. - -K~pøeklopení bloku vèetnì v¹ech podøízených blokù nám staèí invertovat -bit v~koøeni, pokud chceme pøeklopit jen tento blok, invertujeme bity -i v~koøenech v¹ech podøízených blokù, je¾ najdeme obcházením hranice. - -Na~konci algoritmu spustíme dodateèný prùchod, který v¹echny pøeklápìcí -bity pøenese ve~smìru od~koøene k~potomkùm a urèí tak absolutní orientaci -v¹ech seznamù sousedù i hranic. - -\h{®ivý podgraf} - -Kdy¾ nakreslíme nový vrchol~$v$ a z~nìj vedoucí stromové hrany, musíme obejít -ka¾dý podstrom, ve~vhodném poøadí nakreslit zpìtné hrany do~$v$ a podle -potøeby pøeklopit bloky. V~podstromu ov¹em mù¾e být mnoho blokù, které -¾ádnou pozornost nevy¾adují a bìh algoritmu by zbyteènì brzdily. -Proto si pøed samotným kreslením oznaèíme {\I ¾ivou} èást grafu -- to je -èást, kterou potøebujeme bìhem kreslení nav¹tívit; zbytku grafu se budeme -sna¾it vyhýbat, aby nás nezdr¾oval. +\h{Reprezentace bloků a překlápění} + +Pro každý blok si potřebujeme pamatovat vrcholy, které leží na~hranici +(některé z~nich jsou externí, ale to už umíme poznat) a bloky, +které jsou pod nimi připojené. Dále jeÅ¡tě vnitřní strukturu bloku včetně +uvnitř připojených dalších bloků, ale jelikož žádné vnitřní vrcholy nejsou +externí, vnitřek už neovlivní další výpočet a potřebujeme jej pouze +pro vypsání výstupu. + +Pro naÅ¡e účely bude stačit zapamatovat si u~každého bloku, jestli je +oproti nadřazenému bloku překlopen. Tuto informaci zapíšeme do~kořene +bloku. Každý vrchol na~hranici bloku pak bude obsahovat dva~ukazatele +na~sousední vrcholy. Neumíme sice lokálně poznat, který ukazatel odpovídá +kterému směru, ale když se nějakým směrem vydáme, dokážeme ho dodržet +-- stačí si vždy vybrat ten ukazatel, který nás nezavede do~právě +opuÅ¡těného vrcholu. + +Každý vrchol si také bude pamatovat seznam svých sousedů, +podle orientace bloku buďto v~hodinkovém nebo opačném pořadí. +Chceme-li přidat hranu, potřebujeme tedy znát absolutní orientaci, +ale to půjde snadno, jelikož hrany přidáváme jen k~vrcholům na~hranici, +poté co k~nim po~hranici dojdeme z~kořene. + +K~překlopení bloku včetně vÅ¡ech podřízených bloků nám stačí invertovat +bit v~kořeni, pokud chceme překlopit jen tento blok, invertujeme bity +i v~kořenech vÅ¡ech podřízených bloků, jež najdeme obcházením hranice. + +Na~konci algoritmu spustíme dodatečný průchod, který vÅ¡echny překlápěcí +bity přenese ve~směru od~kořene k~potomkům a určí tak absolutní orientaci +vÅ¡ech seznamů sousedů i hranic. + +\h{Živý podgraf} + +Když nakreslíme nový vrchol~$v$ a z~něj vedoucí stromové hrany, musíme obejít +každý podstrom, ve~vhodném pořadí nakreslit zpětné hrany do~$v$ a podle +potřeby překlopit bloky. V~podstromu ovÅ¡em může být mnoho bloků, které +žádnou pozornost nevyžadují a běh algoritmu by zbytečně brzdily. +Proto si před samotným kreslením označíme {\I živou} část grafu -- to je +část, kterou potřebujeme během kreslení navÅ¡tívit; zbytku grafu se budeme +snažit vyhýbat, aby nás nezdržoval. \s{Definice:} -Vrchol~$w$ je {\I ¾ivý,} pokud z~nìj buïto vede zpìtná hrana do~právì -zpracovávaného vrcholu~$v$, nebo pokud pod ním je pøipojen ¾ivý blok, -tj. blok obsahující ¾ivý vrchol. - -®ivé vrcholy pøitom mohou být i~externí (pokud z~nich vedou zpìtné hrany -jak do vrcholu~$v$, tak do je¹tì nenakreslených vrcholù). -Pokud nìjaký vrchol není ani ¾ivý, ani externí, budeme ho nazývat {\I pasivní.} - -Pøed procházením podstromù tedy nejprve probereme v¹echny zpìtné hrany vedoucí do~$v$ -a oznaèíme ¾ivé vrcholy. Pro ka¾dou zpìtnou hranu potøebujeme o¾ivit vrchol, z~nìj¾ -hrana vede, dále artikulaci, pod~ní¾ je tento blok pøipojen, a dal¹í artikulace -na~cestì do~$v$. Tedy poka¾dé, kdy¾ vstoupíme do~bloku (nìjakým vrcholem na~vnìj¹í stìnì), -potøebujeme nalézt koøen bloku. To udìláme tak, ¾e zaèneme obcházet vnìj¹í -stìnu obìma smìry souèasnì, a¾ dojdeme v~nìkterém smìru do~koøene. Navíc si v¹echny -vrcholy, pøes nì¾ jsme pro¹li, oznaèkujeme a pøiøadíme k~nim rovnou ukazatel na~koøen, -tudí¾ po~¾ádné èásti hranice neprojdeme vícekrát.\foot{Znaèky ani nebude potøeba -mazat, kdy¾ si u nich poznamenáme, který vrchol byl koøenem v~okam¾iku, kdy jsme -znaèku vytvoøili, a znaèky patøící ke~starým koøenùm budeme ignorovat, resp. pøepisovat.} - -Výstupem této èásti algoritmu budou znaèky u~¾ivých vrcholù a u~artikulací -také seznamy podøízených ¾ivých blokù. Tyto seznamy budeme udr¾ovat uspoøádané -tak, aby externí bloky následovaly po~v¹ech interních. To nám usnadní práci -v~hlavní èásti algoritmu. - -\s{Lemma:} Pro ka¾dý koøen trvá znaèení ¾ivých vrcholù èas $\O(k+\ell)$, kde $k$ je poèet -kreslených zpìtných hran a $\ell$ poèet hran, které zmizely z~vnìj¹í stìny, èili -amortizovanì konstanta. +Vrchol~$w$ je {\I živý,} pokud z~něj buďto vede zpětná hrana do~právě +zpracovávaného vrcholu~$v$, nebo pokud pod ním je připojen živý blok, +tj. blok obsahující živý vrchol. + +Živé vrcholy přitom mohou být i~externí (pokud z~nich vedou zpětné hrany +jak do vrcholu~$v$, tak do jeÅ¡tě nenakreslených vrcholů). +Pokud nějaký vrchol není ani živý, ani externí, budeme ho nazývat {\I pasivní.} + +Před procházením podstromů tedy nejprve probereme vÅ¡echny zpětné hrany vedoucí do~$v$ +a označíme živé vrcholy. Pro každou zpětnou hranu potřebujeme oživit vrchol, z~nějž +hrana vede, dále artikulaci, pod~níž je tento blok připojen, a další artikulace +na~cestě do~$v$. Tedy pokaždé, když vstoupíme do~bloku (nějakým vrcholem na~vnější stěně), +potřebujeme nalézt kořen bloku. To uděláme tak, že začneme obcházet vnější +stěnu oběma směry současně, až dojdeme v~některém směru do~kořene. Navíc si vÅ¡echny +vrcholy, přes něž jsme proÅ¡li, označkujeme a přiřadíme k~nim rovnou ukazatel na~kořen, +tudíž po~žádné části hranice neprojdeme vícekrát.\foot{Značky ani nebude potřeba +mazat, když si u nich poznamenáme, který vrchol byl kořenem v~okamžiku, kdy jsme +značku vytvořili, a značky patřící ke~starým kořenům budeme ignorovat, resp. přepisovat.} + +Výstupem této části algoritmu budou značky u~živých vrcholů a u~artikulací +také seznamy podřízených živých bloků. Tyto seznamy budeme udržovat uspořádané +tak, aby externí bloky následovaly po~vÅ¡ech interních. To nám usnadní práci +v~hlavní části algoritmu. + +\s{Lemma:} Pro každý kořen trvá značení živých vrcholů čas $\O(k+\ell)$, kde $k$ je počet +kreslených zpětných hran a $\ell$ počet hran, které zmizely z~vnější stěny, čili +amortizovaně konstanta. \proof -Po~¾ádné hranì neprojdeme více ne¾ jednou. Navíc alespoò polovina z~tìch, po~nich¾ -jsme pro¹li, zmizí z~vnìj¹í stìny, tak¾e hledání koøenù blokù trvá $\O(\ell)$. -Pro ka¾dou zpìtnou hranu oznaèíme jeden vrchol jako ¾ivý a pak pokraèujeme hledáním -koøenù, které jsme ji¾ zapoèítali. +Po~žádné hraně neprojdeme více než jednou. Navíc alespoň polovina z~těch, po~nichž +jsme proÅ¡li, zmizí z~vnější stěny, takže hledání kořenů bloků trvá $\O(\ell)$. +Pro každou zpětnou hranu označíme jeden vrchol jako živý a pak pokračujeme hledáním +kořenů, které jsme již započítali. \qed -\h{Kreslení zpìtných hran} +\h{Kreslení zpětných hran} -Nyní ji¾ máme v¹e pøipraveno -- datové struktury, detekci externích vrcholù -a oznaèování ¾ivého podgrafu -- a zbývá doplnit, jak algoritmus kreslí zpìtné -hrany. Jeliko¾ zpìtné hrany vedoucí do~$v$ nemohou zpùsobit slouèení blokù -le¾ících pod~$v$ (na~to jsou potøeba zpìtné hrany vedoucí nìkam nad~$v$ a ty -je¹tì nekreslíme), zpracováváme ka¾dý podstrom zvlá¹». V¾dy pøidáme triviální blok -pro stromovou hranu, pod nìj pøipojíme blokovou strukturu zatím nakreslené -èásti podstromu a vydáme se po~hranici této struktury nejdøíve jedním -a pak druhým smìrem. +Nyní již máme vÅ¡e připraveno -- datové struktury, detekci externích vrcholů +a označování živého podgrafu -- a zbývá doplnit, jak algoritmus kreslí zpětné +hrany. Jelikož zpětné hrany vedoucí do~$v$ nemohou způsobit sloučení bloků +ležících pod~$v$ (na~to jsou potřeba zpětné hrany vedoucí někam nad~$v$ a ty +jeÅ¡tě nekreslíme), zpracováváme každý podstrom zvlášť. Vždy přidáme triviální blok +pro stromovou hranu, pod něj připojíme blokovou strukturu zatím nakreslené +části podstromu a vydáme se po~hranici této struktury nejdříve jedním +a pak druhým směrem. -Oba prùchody vypadají následovnì: Procházíme seznam vrcholù na~hranici a pasivní -vrcholy pøeskakujeme. Pokud objevíme ¾ivý vrchol, nakreslíme v¹e, co z~nìj vede, -pøípadnì se zanoøíme do~¾ivých blokù, které jsou pøipojeny pod tímto vrcholem. -Pokud objevíme externí vrchol (poté, co jsme ho pøípadnì o¹etøili jako ¾ivý), -procházení zastavíme, proto¾e za externí vrchol ji¾ nemù¾eme po~této stranì -hranice nic pøipojit, ani¾ by se externí vrchol dostal dovnitø nakreslení. +Oba průchody vypadají následovně: Procházíme seznam vrcholů na~hranici a pasivní +vrcholy přeskakujeme. Pokud objevíme živý vrchol, nakreslíme vÅ¡e, co z~něj vede, +případně se zanoříme do~živých bloků, které jsou připojeny pod tímto vrcholem. +Pokud objevíme externí vrchol (poté, co jsme ho případně oÅ¡etřili jako živý), +procházení zastavíme, protože za externí vrchol již nemůžeme po~této straně +hranice nic připojit, aniž by se externí vrchol dostal dovnitř nakreslení. -Pøitom se øídíme dvìma jednoduchými pravidly: +Přitom se řídíme dvěma jednoduchými pravidly: -\s{Pravidlo \#1:} V~ka¾dém ¾ivém vrcholu zpracováváme nejdøíve zpìtné hrany do~$v$, -pak podøízené ¾ivé interní bloky a koneènì podøízené ¾ivé externí bloky. -(K~tomu se nám hodí, ¾e máme seznamy ¾ivých podøízených blokù setøídìné.) +\s{Pravidlo \#1:} V~každém živém vrcholu zpracováváme nejdříve zpětné hrany do~$v$, +pak podřízené živé interní bloky a konečně podřízené živé externí bloky. +(K~tomu se nám hodí, že máme seznamy živých podřízených bloků setříděné.) -\s{Pravidlo \#2:} Pokud vstoupíme do~dal¹ího bloku, vybereme si smìr, ve~kterém -budeme pokraèovat, následovnì: preferujeme smìr k~¾ivému internímu -vrcholu, pokud takový neexistuje, pak k~¾ivému externímu vrcholu. -Pokud se tento smìr li¹í od~smìru, ve~kterém jsme zatím hranici obcházeli, -blok pøeklopíme. +\s{Pravidlo \#2:} Pokud vstoupíme do~dalšího bloku, vybereme si směr, ve~kterém +budeme pokračovat, následovně: preferujeme směr k~živému internímu +vrcholu, pokud takový neexistuje, pak k~živému externímu vrcholu. +Pokud se tento směr liší od~směru, ve~kterém jsme zatím hranici obcházeli, +blok překlopíme. -Èasová slo¾itost této èásti algoritmu je lineární ve~velikosti ¾ivého podgrafu -a¾ na~dvì výjimky. Jednou je konec prohledávání od~posledního ¾ivého vrcholu -k~bodu zastavení, druhou pak vybírání strany hranice pøi vstupu do~bloku. -V~obou mù¾eme procházet a¾ lineárnì mnoho pasivních vrcholù. Pomù¾eme si -ov¹em snadno: kdykoliv projdeme souvislý úsek hranice tvoøený pasivními -vrcholy, pøidáme pomocnou hranu, která tento úsek pøeklene. Mù¾eme ji dokonce -pøidat do~nakreslení a podrozdìlit si tak vnìj¹í stìnu. +Časová složitost této části algoritmu je lineární ve~velikosti živého podgrafu +až na~dvě výjimky. Jednou je konec prohledávání od~posledního živého vrcholu +k~bodu zastavení, druhou pak vybírání strany hranice při vstupu do~bloku. +V~obou můžeme procházet až lineárně mnoho pasivních vrcholů. Pomůžeme si +ovÅ¡em snadno: kdykoliv projdeme souvislý úsek hranice tvořený pasivními +vrcholy, přidáme pomocnou hranu, která tento úsek překlene. Můžeme ji dokonce +přidat do~nakreslení a podrozdělit si tak vnější stěnu. -\h{Hotový algoritmus} +\h{Hotový algoritmus} -\s{Algoritmus (kreslení do roviny):} +\s{Algoritmus (kreslení do roviny):} \algo -\:Pokud má graf více ne¾ $3n-6$ hran, odmítneme ho rovnou jako nerovinný. -\:Prohledáme graf $G$ do~hloubky, spoèteme \ \ a \ v¹ech vrcholù. -\:Vytvoøíme \ v¹ech vrcholù pøihrádkovým tøídìním. -\:Procházíme vrcholy v~poøadí klesajících \ù, pro ka¾dý vrchol~$v$: -\::Nakreslíme v¹echny stromové hrany z~$v$ jako triviální bloky \hfil\break (2-cykly). -\::Oznaèíme ¾ivý podgraf. -\::Pro ka¾dého syna vrcholu~$v$ obcházíme ¾ivý podgraf nále¾ící k~tomuto vrcholu - v~obou smìrech a kreslíme zpìtné hrany do~$v$. -\::Zkontrolujeme, zda v¹echny zpìtné hrany vedoucí do~$v$ byly nakresleny, a pokud ne, - prohlásíme graf za~nerovinný a skonèíme. -\:Projdeme hotové nakreslení do~hloubky a zorientujeme seznamy sousedù. +\:Pokud má graf více než $3n-6$ hran, odmítneme ho rovnou jako nerovinný. +\:Prohledáme graf $G$ do~hloubky, spočteme \ \ a \ vÅ¡ech vrcholů. +\:Vytvoříme \ vÅ¡ech vrcholů přihrádkovým tříděním. +\:Procházíme vrcholy v~pořadí klesajících \ů, pro každý vrchol~$v$: +\::Nakreslíme vÅ¡echny stromové hrany z~$v$ jako triviální bloky \hfil\break (2-cykly). +\::Označíme živý podgraf. +\::Pro každého syna vrcholu~$v$ obcházíme živý podgraf náležící k~tomuto vrcholu + v~obou směrech a kreslíme zpětné hrany do~$v$. +\::Zkontrolujeme, zda vÅ¡echny zpětné hrany vedoucí do~$v$ byly nakresleny, a pokud ne, + prohlásíme graf za~nerovinný a skončíme. +\:Projdeme hotové nakreslení do~hloubky a zorientujeme seznamy sousedů. \endalgo -\s{Vìta:} Tento algoritmus pro ka¾dý graf dobìhne v~èase $\O(n)$ a pokud byl graf rovinný, -vydá jeho nakreslení, v~opaèném pøípadì ohlásí nerovinnost. +\s{Věta:} Tento algoritmus pro každý graf doběhne v~čase $\O(n)$ a pokud byl graf rovinný, +vydá jeho nakreslení, v~opačném případě ohlásí nerovinnost. -\proof První krok je korektní, jeliko¾ pro v¹echny rovinné grafy je $m\le 3n-6$; nadále -tedy mù¾eme pøedpokládat, ¾e $m=\O(n)$. Lineární èasovou slo¾itost krokù 4--6 a~9 jsme ji¾ -diskutovali, kroky~7--8 jsou lineární ve~velikosti ¾ivého podgrafu, a~tedy také $\O(n)$. -Nakreslení vydané algoritmem je v¾dy rovinné a v¹echny stromové hrany jsou v¾dy -nakresleny, zbývá tedy ukázat, ¾e zpìtnou hranu mù¾eme nenakreslit, jen pokud -graf nebyl rovinný. Tomu vìnujeme zbytek kapitoly. +\proof První krok je korektní, jelikož pro vÅ¡echny rovinné grafy je $m\le 3n-6$; nadále +tedy můžeme předpokládat, že $m=\O(n)$. Lineární časovou složitost kroků 4--6 a~9 jsme již +diskutovali, kroky~7--8 jsou lineární ve~velikosti živého podgrafu, a~tedy také $\O(n)$. +Nakreslení vydané algoritmem je vždy rovinné a vÅ¡echny stromové hrany jsou vždy +nakresleny, zbývá tedy ukázat, že zpětnou hranu můžeme nenakreslit, jen pokud +graf nebyl rovinný. Tomu věnujeme zbytek kapitoly. \qed -\h{Dùkaz korektnosti} +\h{Důkaz korektnosti} -\s{Lemma:} Pokud existuje zpìtná hrana, kterou algoritmus nenakreslil, graf na~vstupu -není rovinný. +\s{Lemma:} Pokud existuje zpětná hrana, kterou algoritmus nenakreslil, graf na~vstupu +není rovinný. -\proof Pro spor pøedpokládejme, ¾e po~zpracování vrcholu~$v$ existuje nìjaká -zpìtná hrana~$wv$, kterou algoritmus nenakreslil, èili ¾e pøístup z~$v$ k~$w$ -je v~obou smìrech blokován externími vrcholy. Rozborem pøípadù uká¾eme, -¾e tato situace vede ke~sporu buïto s~pravidly \#1 a \#2 nebo s~rovinností grafu. +\proof Pro spor předpokládejme, že po~zpracování vrcholu~$v$ existuje nějaká +zpětná hrana~$wv$, kterou algoritmus nenakreslil, čili že přístup z~$v$ k~$w$ +je v~obou směrech blokován externími vrcholy. Rozborem případů ukážeme, +že tato situace vede ke~sporu buďto s~pravidly \#1 a \#2 nebo s~rovinností grafu. -Oznaème $B$ blok, ve~kterém le¾í na~obou stranách hranice nìjaké externí -vrcholy $x$ a~$y$ a pod nimi je pøipojen nìjakou cestou vrchol~$w$. Takový blok -musí urèitì existovat, proto¾e jinak by algoritmus v¹echny bloky na~cestì z~$v$ do~$w$ -popøeklápìl tak, aby se hrana $wv$ ve¹la. V~grafu se tedy musí vyskytovat jeden -z~následujících minorù (do~vrcholu~$u$ jsme kontrahovali celou dosud nenakreslenou èást grafu; -vybarvená èást odpovídá vnitøku bloku; hranaté vrcholy jsou externí): +Označme $B$ blok, ve~kterém leží na~obou stranách hranice nějaké externí +vrcholy $x$ a~$y$ a pod nimi je připojen nějakou cestou vrchol~$w$. Takový blok +musí určitě existovat, protože jinak by algoritmus vÅ¡echny bloky na~cestě z~$v$ do~$w$ +popřeklápěl tak, aby se hrana $wv$ veÅ¡la. V~grafu se tedy musí vyskytovat jeden +z~následujících minorů (do~vrcholu~$u$ jsme kontrahovali celou dosud nenakreslenou část grafu; +vybarvená část odpovídá vnitřku bloku; hranaté vrcholy jsou externí): \bigskip \centerline{\epsfbox{minor1.eps}\qquad\epsfbox{minor2.eps}} \bigskip -Minor~$M$ pøitom odpovídá situaci, kdy $v$ nele¾í v~bloku~$B$. Tento pøípad -snadno vylouèíme, proto¾e $M$ je isomorfní s~grafem $K_{3,3}$. V~grafu se proto -musí vyskytovat~$N$. Tento minor je ale rovinný, tak¾e musíme ukázat, ¾e vnitøek -bloku brání nakreslení hrany~$vw$ dovnitø. V¾dy pak dojdeme k~nìkterému z~následujících -nerovinných minorù ($N_1$ a¾ $N_3$ jsou isomorfní s~$K_{3,3}$ a $N_4$ s~$K_5$): +Minor~$M$ přitom odpovídá situaci, kdy $v$ neleží v~bloku~$B$. Tento případ +snadno vyloučíme, protože $M$ je isomorfní s~grafem $K_{3,3}$. V~grafu se proto +musí vyskytovat~$N$. Tento minor je ale rovinný, takže musíme ukázat, že vnitřek +bloku brání nakreslení hrany~$vw$ dovnitř. Vždy pak dojdeme k~některému z~následujících +nerovinných minorů ($N_1$ až $N_3$ jsou isomorfní s~$K_{3,3}$ a $N_4$ s~$K_5$): \bigskip \centerline{\epsfbox{minor3.eps}\qquad\epsfbox{minor4.eps}} @@ -342,45 +342,45 @@ nerovinn \centerline{\epsfbox{minor5.eps}\qquad\epsfbox{minor6.eps}} \bigskip -\>Uva¾me, jak bude $B$ vypadat po~odebrání vrcholu~$v$ a hran z~nìj vedoucích: +\>Uvažme, jak bude $B$ vypadat po~odebrání vrcholu~$v$ a hran z~něj vedoucích: \numlist\nalpha -\:{\I pøestane být 2-souvislý} -- tehdy se zamìøíme na~bloky le¾ící na~cestì~$xy$: +\:{\I přestane být 2-souvislý} -- tehdy se zaměříme na~bloky ležící na~cestě~$xy$: \numlist\nparen \finalfix{\rightskip=0.5\rightskip} -\:{\I $w$ je artikulace} na této cestì -- BÚNO je taková artikulace v~DFS prohledána po~bloku obsahujícím~$x$, -ale pøed~$y$. Tehdy nám jistì $x$ nezabránilo v~tom, abychom do~$w$ do¹li (mù¾e blokovat -jenom jednu stranu hranice), tak¾e jsme se ve~$w$ museli rozhodnout, ¾e pøednostnì zpracujeme -pokraèování cesty do~$y$ pøed hranou~$vw$, a~to je spor s~pravidlem~\#1. - -\:{\I $w$ je v~bloku pøipojeném pod takovou artikulací} -- aby se pravidlo~\#1 vydalo -do~$y$ místo podøízených blokù, musí být alespoò jeden z~nich externí, -tak¾e v~$G$ je minor~$N_1$. - -\:{\I $w$ je v~bloku na~cestì nebo pøipojen pod takový blok} -- opìt si v¹imneme, ¾e do~bloku jsme -vstoupili mezi~$x$ a~$y$. Abychom se podle pravidla~\#2 rozhodli pro stranu, z~ní¾ nevede -hrana~$vw$, musela na~druhé stranì být také hrana do~$v$, a~proto se v~grafu vyskytuje minor~$M$. +\:{\I $w$ je artikulace} na této cestě -- BÚNO je taková artikulace v~DFS prohledána po~bloku obsahujícím~$x$, +ale před~$y$. Tehdy nám jistě $x$ nezabránilo v~tom, abychom do~$w$ doÅ¡li (může blokovat +jenom jednu stranu hranice), takže jsme se ve~$w$ museli rozhodnout, že přednostně zpracujeme +pokračování cesty do~$y$ před hranou~$vw$, a~to je spor s~pravidlem~\#1. + +\:{\I $w$ je v~bloku připojeném pod takovou artikulací} -- aby se pravidlo~\#1 vydalo +do~$y$ místo podřízených bloků, musí být alespoň jeden z~nich externí, +takže v~$G$ je minor~$N_1$. + +\:{\I $w$ je v~bloku na~cestě nebo připojen pod takový blok} -- opět si vÅ¡imneme, že do~bloku jsme +vstoupili mezi~$x$ a~$y$. Abychom se podle pravidla~\#2 rozhodli pro stranu, z~níž nevede +hrana~$vw$, musela na~druhé straně být také hrana do~$v$, a~proto se v~grafu vyskytuje minor~$M$. \endlist -\:{\I zùstane 2-souvislý} a vznikne z~nìj nìjaký blok~$B'$ -- tehdy rozebereme, jaké hrany vedou mezi $v$ a $B'$: +\:{\I zůstane 2-souvislý} a vznikne z~něj nějaký blok~$B'$ -- tehdy rozebereme, jaké hrany vedou mezi $v$ a $B'$: \numlist\nparen \finalfix{\rightskip=0.5\rightskip} -\:{\I více ne¾ dvì hrany} -- minor~$N_2$. -\:{\I alespoò jedna hrana na \uv{horní} cestu} (to jest na~tu, na~ni¾ nele¾í~$w$) -- minor~$N_3$. -\:{\I dvì hrany do~$x,y$ nebo na \uv{dolní} cestu} -- a» u¾ jsme vstoupili na~hranici bloku~$B'$ -kteroukoliv hranou, pravidlo~\#2 nám øeklo, ¾e máme pokraèovat vrchem, co¾ je mo¾né jedinì tehdy, -je-li na~spodní cestì je¹tì jeden externí vrchol, a~to dává minor~$N_4$. +\:{\I více než dvě hrany} -- minor~$N_2$. +\:{\I alespoň jedna hrana na \uv{horní} cestu} (to jest na~tu, na~niž neleží~$w$) -- minor~$N_3$. +\:{\I dvě hrany do~$x,y$ nebo na \uv{dolní} cestu} -- aÅ¥ už jsme vstoupili na~hranici bloku~$B'$ +kteroukoliv hranou, pravidlo~\#2 nám řeklo, že máme pokračovat vrchem, což je možné jedině tehdy, +je-li na~spodní cestě jeÅ¡tě jeden externí vrchol, a~to dává minor~$N_4$. \qeditem \endlist \endlist -\s{Poznámka:} Podle tohoto dùkazu bychom také mohli v~lineárním èase v~ka¾dém nerovinném -grafu nalézt Kuratowského podgraf, dokonce také v~$O(n)$, jeliko¾ kdy¾ je $m>3n-6$, -mù¾eme se omezit na~libovolných $3n-5$ hran, které urèitì tvoøí nerovinný podgraf. +\s{Poznámka:} Podle tohoto důkazu bychom také mohli v~lineárním čase v~každém nerovinném +grafu nalézt Kuratowského podgraf, dokonce také v~$O(n)$, jelikož když je $m>3n-6$, +můžeme se omezit na~libovolných $3n-5$ hran, které určitě tvoří nerovinný podgraf. \references \bye diff --git a/11-planar/slides/planar.tex b/11-planar/slides/planar.tex index cce7431..9d53f61 100644 --- a/11-planar/slides/planar.tex +++ b/11-planar/slides/planar.tex @@ -3,81 +3,81 @@ \usepackage[czech]{babel} \usepackage{palatino} \usetheme{Warsaw} -\title[Kreslení grafù do roviny]{Kreslení grafù do roviny} -\author[Martin Mare¹]{Martin Mare¹\\\texttt{mj@ucw.cz}} +\title[Kreslení grafů do roviny]{Kreslení grafů do roviny} +\author[Martin MareÅ¡]{Martin MareÅ¡\\\texttt{mj@ucw.cz}} \institute{Charles University in Prague\\Faculty of Math and Physics\\Department of Applied Mathematics} \date{} \begin{document} \setbeamertemplate{navigation symbols}{} \setbeamerfont{title page}{family=\rmfamily} -\begin{frame}{Stavy vrcholù} +\begin{frame}{Stavy vrcholů} -Pøi kreslení vrcholu~$v$ budeme oznaèovat vrcholy v~u¾ nakreslené -èásti takto: +Při kreslení vrcholu~$v$ budeme označovat vrcholy v~už nakreslené +části takto: ~ \begin{itemize} \item -Vrchol~$w$ je {\bf externí,} pokud z~nìj vede zpìtná hrana do~je¹tì -nenakreslené èásti grafu (\uv{nad $v$}), nebo pokud je artikulací, -pod ní¾ je pøipojen podgraf obsahující takový vrchol. Ostatní vrcholy -jsou {\bf interní.} +Vrchol~$w$ je {\bf externí,} pokud z~něj vede zpětná hrana do~jeÅ¡tě +nenakreslené části grafu (\uv{nad $v$}), nebo pokud je artikulací, +pod níž je připojen podgraf obsahující takový vrchol. Ostatní vrcholy +jsou {\bf interní.} \item -Vrchol~$w$ je {\bf ¾ivý,} pokud z~nìj vede zpìtná hrana do~$v$ -nebo pokud je pod ním pøipojen blok s~¾ivým vrcholem. +Vrchol~$w$ je {\bf živý,} pokud z~něj vede zpětná hrana do~$v$ +nebo pokud je pod ním připojen blok s~živým vrcholem. \item -Podobnì pro bloky (podle koøene) a zpìtné hrany. +Podobně pro bloky (podle kořene) a zpětné hrany. \end{itemize} \end{frame} -\begin{frame}{Pravidla obcházení} +\begin{frame}{Pravidla obcházení} {\bf P1:} -V~ka¾dém ¾ivém vrcholu zpracováváme: +V~každém živém vrcholu zpracováváme: \begin{enumerate} -\item zpìtné hrany do~$v$ -\item podøízené ¾ivé interní bloky -\item podøízené ¾ivé externí bloky +\item zpětné hrany do~$v$ +\item podřízené živé interní bloky +\item podřízené živé externí bloky \end{enumerate} ~ {\bf P2:} -Vstoupíme-li do podøízeného bloku, vybereme si smìr: +Vstoupíme-li do podřízeného bloku, vybereme si směr: \begin{enumerate} -\item k~¾ivému internímu vrcholu -\item k~¾ivému externímu vrcholu +\item k~živému internímu vrcholu +\item k~živému externímu vrcholu \end{enumerate} -Pokud se tento smìr li¹í od~dosavadního, podøízený blok a v¹e pod ním -pøeklopíme. +Pokud se tento směr liší od~dosavadního, podřízený blok a vÅ¡e pod ním +překlopíme. \end{frame} \begin{frame}{Algoritmus} \begin{enumerate} -\item Pokud má graf více ne¾ $3n-6$ hran $\Rightarrow$ {\sc nerovinný.} -\item Prohledáme graf do hloubky: {\it Enter, Ancestor, LowPoint.} -\item<3-> Sestrojíme {\it BlockList}y a setøídíme je. -\item Pro vrcholy~$v$ v~poøadí klesajících {\it Enter\/}ù kreslíme: -\item Nakreslíme stromové hrany z~$v$ dolù jako triviální bloky (2-cykly). +\item Pokud má graf více než $3n-6$ hran $\Rightarrow$ {\sc nerovinný.} +\item Prohledáme graf do hloubky: {\it Enter, Ancestor, LowPoint.} +\item<3-> Sestrojíme {\it BlockList}y a setřídíme je. +\item Pro vrcholy~$v$ v~pořadí klesajících {\it Enter\/}ů kreslíme: +\item Nakreslíme stromové hrany z~$v$ dolů jako triviální bloky (2-cykly). \advance\leftskip by 2em -\item<4-> Oznaèíme ¾ivý podgraf. -\item Pro ka¾dého syna vrcholu~$v$ obcházíme hranici v~obou smìrech - a kreslíme zpìtné hrany do~$v$. Øídíme se pravidly {\bf P1} a {\bf P2,} - za externím vrcholem se zastavíme. -\item Zbývá-li nìjaká zpìtná hrana do~$v$ $\Rightarrow$ {\sc nerovinný.} +\item<4-> Označíme živý podgraf. +\item Pro každého syna vrcholu~$v$ obcházíme hranici v~obou směrech + a kreslíme zpětné hrany do~$v$. Řídíme se pravidly {\bf P1} a {\bf P2,} + za externím vrcholem se zastavíme. +\item Zbývá-li nějaká zpětná hrana do~$v$ $\Rightarrow$ {\sc nerovinný.} \advance\leftskip by -2em -\item<2-> Zorientujeme seznamy sousedù $\Rightarrow$ hotové nakreslení. +\item<2-> Zorientujeme seznamy sousedů $\Rightarrow$ hotové nakreslení. \end{enumerate} \end{frame} diff --git a/12-randcut/12-randcut.tex b/12-randcut/12-randcut.tex index ce522b8..feb2c91 100644 --- a/12-randcut/12-randcut.tex +++ b/12-randcut/12-randcut.tex @@ -1,50 +1,50 @@ \input ../sgr.tex -\prednaska{12}{Pravdìpodobnostní algoritmus na øezy}{} +\prednaska{12}{Pravděpodobnostní algoritmus na řezy}{} -Nahlédnìme alespoò jednou kapitolou do~svìta pravdìpodobnostních algoritmù. -Není toti¾ výjimkou, ¾e s~pomocí generátoru náhodných èísel vyøe¹íme nìkteré -grafové problémy daleko snáze a èasto také efektivnìji, ne¾ to dovedeme deterministicky. -Pravdìpodobnostní pøístup si pøedvedeme na~Kargerovì-Steinovì algoritmu \cite{karger:mincut} -pro hledání minimálního øezu v~neohodnoceném neorientovaném grafu. Pøipomeòme, -¾e s~deterministickými algoritmy jsme zatím dosáhli èasové slo¾itosti $\O(n^{5/3}m)$ -pomocí tokù nebo $\O(nm)$ Nagamochiho-Ibarakiho algoritmem. +Nahlédněme alespoň jednou kapitolou do~světa pravděpodobnostních algoritmů. +Není totiž výjimkou, že s~pomocí generátoru náhodných čísel vyřešíme některé +grafové problémy daleko snáze a často také efektivněji, než to dovedeme deterministicky. +Pravděpodobnostní přístup si předvedeme na~Kargerově-Steinově algoritmu \cite{karger:mincut} +pro hledání minimálního řezu v~neohodnoceném neorientovaném grafu. Připomeňme, +že s~deterministickými algoritmy jsme zatím dosáhli časové složitosti $\O(n^{5/3}m)$ +pomocí toků nebo $\O(nm)$ Nagamochiho-Ibarakiho algoritmem. -\h{Náhodné kontrakce} +\h{Náhodné kontrakce} -Uva¾ujme nejdøíve následující algoritmus, který náhodnì vybírá -hrany a kontrahuje je, dokud poèet vrcholù neklesne na~danou hodnotu~$\ell$. +Uvažujme nejdříve následující algoritmus, který náhodně vybírá +hrany a kontrahuje je, dokud počet vrcholů neklesne na~danou hodnotu~$\ell$. \s{Algoritmus} $\hbox{\sc Contract}(G_0,\ell)$: \algo \:$G \leftarrow G_0$. \:Dokud $n>\ell$: -\::Vybereme hranu $e\in E$ rovnomìrnì náhodnì. -\::$G \leftarrow G/e$ (kontrahujeme hranu~$e$, smyèky odstraòujeme, - paralelní hrany ponecháme). -\:Vrátíme jako výsledek graf~$G$. +\::Vybereme hranu $e\in E$ rovnoměrně náhodně. +\::$G \leftarrow G/e$ (kontrahujeme hranu~$e$, smyčky odstraňujeme, + paralelní hrany ponecháme). +\:Vrátíme jako výsledek graf~$G$. \endalgo -Jaká je pravdìpodobnost, ¾e výsledný graf~$G$ má stejnì velký minimální øez -jako zadaný graf~$G_0$? V¹imnìme si nejprve, ¾e ka¾dý øez v~grafu $G/e$ je i øezem -v~grafu~$G$ (a¾ na pøeznaèení hran pøi kontrakci, ale pøedpokládejme, ¾e hrany -mají nìjaké identifikátory, které kontrakce zachovává). Podobnì je-li v~grafu~$G$ -øez neobsahující hranu~$e$, odpovídá mu stejnì velký øez v~$G/e$. Velikost -minimálního øezu tedy kontrakcí nikdy neklesne -- mù¾e pouze stoupnout, pokud -skontrahujeme hranu le¾ící ve~v¹ech minimálních øezech, - -Zvolíme nyní pevnì jeden z~minimálních øezù~$C$ v~zadaném grafu~$G_0$ a oznaèíme~$k$ jeho -velikost. Pokud algoritmus ani jednou nevybere hranu le¾ící v~tomto øezu, velikost -minimálního øezu v~grafu~$G$ bude rovnì¾ rovna~$k$. Jaká je pravdìpodobnost, ¾e +Jaká je pravděpodobnost, že výsledný graf~$G$ má stejně velký minimální řez +jako zadaný graf~$G_0$? VÅ¡imněme si nejprve, že každý řez v~grafu $G/e$ je i řezem +v~grafu~$G$ (až na přeznačení hran při kontrakci, ale předpokládejme, že hrany +mají nějaké identifikátory, které kontrakce zachovává). Podobně je-li v~grafu~$G$ +řez neobsahující hranu~$e$, odpovídá mu stejně velký řez v~$G/e$. Velikost +minimálního řezu tedy kontrakcí nikdy neklesne -- může pouze stoupnout, pokud +skontrahujeme hranu ležící ve~vÅ¡ech minimálních řezech, + +Zvolíme nyní pevně jeden z~minimálních řezů~$C$ v~zadaném grafu~$G_0$ a označíme~$k$ jeho +velikost. Pokud algoritmus ani jednou nevybere hranu ležící v~tomto řezu, velikost +minimálního řezu v~grafu~$G$ bude rovněž rovna~$k$. Jaká je pravděpodobnost, že se tak stane? -Oznaème $G_i$ stav grafu~$G$ pøed $i$-tým prùchodem cyklem a $n_i$ a $m_i$ poèet jeho -vrcholù a hran. Zøejmì $n_i=n-i+1$ (ka¾dou kontrakcí pøijdeme o~jeden vrchol). -Navíc ka¾dý vrchol má stupeò alespoò~$k$, jeliko¾ jinak by triviální øez okolo -tohoto vrcholu byl men¹í ne¾ minimální øez. Proto platí $m_i \ge kn_i/2$. Hranu -le¾ící v~øezu~$C$ tedy vybereme s~pravdìpodobností nejvý¹e $k/m_i \le k/(kn_i/2) = 2/n_i -= 2/(n-i+1)$. V¹echny hrany z~øezu~$C$ proto postoupí do výsledného grafu~$G$ -s~pravdìpodobností +Označme $G_i$ stav grafu~$G$ před $i$-tým průchodem cyklem a $n_i$ a $m_i$ počet jeho +vrcholů a hran. Zřejmě $n_i=n-i+1$ (každou kontrakcí přijdeme o~jeden vrchol). +Navíc každý vrchol má stupeň alespoň~$k$, jelikož jinak by triviální řez okolo +tohoto vrcholu byl menší než minimální řez. Proto platí $m_i \ge kn_i/2$. Hranu +ležící v~řezu~$C$ tedy vybereme s~pravděpodobností nejvýše $k/m_i \le k/(kn_i/2) = 2/n_i += 2/(n-i+1)$. VÅ¡echny hrany z~řezu~$C$ proto postoupí do výsledného grafu~$G$ +s~pravděpodobností $$\eqalign{ p &\ge \prod_{i=1}^{n-\ell} \left( 1 - {2\over n-i+1} \right) = \prod_{i=1}^{n-\ell} {n-i-1 \over n-i+1} = \cr @@ -52,53 +52,53 @@ p &\ge \prod_{i=1}^{n-\ell} \left( 1 - {2\over n-i+1} \right) = {\ell\cdot(\ell-1) \over n\cdot(n-1)}. \cr }$$ -Mù¾eme tedy zvolit pevnì~$\ell$, spustit na~zadaný graf proceduru {\sc Contract} -a ve~vzniklém konstantnì velkém grafu pak nalézt minimální øez hrubou silou -(to je obzvlá¹tì snadné pro $\ell=2$ -- tehdy staèí vzít v¹echny zbylé hrany). -Takový algoritmus nalezne minimální øez s~pravdìpodobností alespoò $c/n^2$, -kde~$c$ je konstanta závislá na~$\ell$. - -Nabízí se otázka, k~èemu je dobrý algoritmus, který vydá správný výsledek -s~pravdìpodobností na~øádu $1/n^2$. To opravdu není mnoho, ale stejnì jako -mnoho jiných randomizovaných algoritmù i tento mù¾eme iterovat: výpoèet -zopakujeme $K$-krát a pou¾ijeme nejmen¹í z~nalezených øezù. Ten u¾ bude -minimální s~pravdìpodobností +Můžeme tedy zvolit pevně~$\ell$, spustit na~zadaný graf proceduru {\sc Contract} +a ve~vzniklém konstantně velkém grafu pak nalézt minimální řez hrubou silou +(to je obzvláště snadné pro $\ell=2$ -- tehdy stačí vzít vÅ¡echny zbylé hrany). +Takový algoritmus nalezne minimální řez s~pravděpodobností alespoň $c/n^2$, +kde~$c$ je konstanta závislá na~$\ell$. + +Nabízí se otázka, k~čemu je dobrý algoritmus, který vydá správný výsledek +s~pravděpodobností na~řádu $1/n^2$. To opravdu není mnoho, ale stejně jako +mnoho jiných randomizovaných algoritmů i tento můžeme iterovat: výpočet +zopakujeme $K$-krát a použijeme nejmenší z~nalezených řezů. Ten už bude +minimální s~pravděpodobností $$ P_K \ge 1 - (1-c/n^2)^K \ge 1 - e^{-cK/n^2}. $$ -(Druhá nerovnost platí díky tomu, ¾e $e^{-x} \ge 1-x$ pro v¹echna $x\ge 0$.) -Pokud tedy nastavíme poèet opakování~$K$ na $\Omega(n^2)$, mù¾eme tím pravdìpodobnost -chyby stlaèit pod libovolnou konstantu, pro $K=\Omega(n^2\log n)$ pod pøevrácenou -hodnotu libovolného polynomu v~$n$ a pro $K=\Omega(n^3)$ u¾ bude dokonce exponenciálnì malá. +(Druhá nerovnost platí díky tomu, že $e^{-x} \ge 1-x$ pro vÅ¡echna $x\ge 0$.) +Pokud tedy nastavíme počet opakování~$K$ na $\Omega(n^2)$, můžeme tím pravděpodobnost +chyby stlačit pod libovolnou konstantu, pro $K=\Omega(n^2\log n)$ pod převrácenou +hodnotu libovolného polynomu v~$n$ a pro $K=\Omega(n^3)$ už bude dokonce exponenciálně malá. \h{Implementace} -Odboème na chvíli k~implementaèním zále¾itostem. Jak reprezentovat graf, abychom -stihli rychle provádìt kontrakce? Bude nám staèit obyèejná matice sousednosti, -v~ní¾ pro ka¾dou dvojici vrcholù budeme udr¾ovat, kolik paralelních hran mezi tìmito vrcholy -vede. Pokud chceme kontrahovat hranu~$uv$, staèí projít v¹echny hrany vedoucí -(øeknìme) z~vrcholu~$u$ a zaøadit je k~vrcholu~$v$. To zvládneme v~èase $\O(n)$ +Odbočme na chvíli k~implementačním záležitostem. Jak reprezentovat graf, abychom +stihli rychle provádět kontrakce? Bude nám stačit obyčejná matice sousednosti, +v~níž pro každou dvojici vrcholů budeme udržovat, kolik paralelních hran mezi těmito vrcholy +vede. Pokud chceme kontrahovat hranu~$uv$, stačí projít vÅ¡echny hrany vedoucí +(řekněme) z~vrcholu~$u$ a zařadit je k~vrcholu~$v$. To zvládneme v~čase $\O(n)$ na jednu kontrakci. -Pro náhodný výbìr hrany budeme udr¾ovat pole stupòù vrcholù, vybereme náhodnì -vrchol~$v$ s~pravdìpodobností úmìrnou stupni a poté projitím pøíslu¹ného øádku -matice sousednosti druhý vrchol~$v$ s~pravdìpodobností úmìrnou poètu hran -mezi $u$ a~$v$. To opìt trvá èas $\O(n)$. +Pro náhodný výběr hrany budeme udržovat pole stupňů vrcholů, vybereme náhodně +vrchol~$v$ s~pravděpodobností úměrnou stupni a poté projitím přísluÅ¡ného řádku +matice sousednosti druhý vrchol~$v$ s~pravděpodobností úměrnou počtu hran +mezi $u$ a~$v$. To opět trvá čas $\O(n)$. -Procedura {\sc Contract} tedy pracuje v~èase $\O((n-\ell)\cdot n)$ a celý -$K$-krát ziterovaný algoritmus v~$\O(Kn^2)$. Pokud se spokojíme s~pøevrácenì -polynomiální pravdìpodobností chyby, nalezneme minimální øez v~èase $\O(n^4\log n)$. +Procedura {\sc Contract} tedy pracuje v~čase $\O((n-\ell)\cdot n)$ a celý +$K$-krát ziterovaný algoritmus v~$\O(Kn^2)$. Pokud se spokojíme s~převráceně +polynomiální pravděpodobností chyby, nalezneme minimální řez v~čase $\O(n^4\log n)$. -\h{Kargerùv-Steinùv algoritmus} +\h{Kargerův-Steinův algoritmus} -Pøedchozí prostinký algoritmus mù¾eme je¹tì podstatnì vylep¹it. -V¹imnìme si, ¾e bìhem kontrahování hran pravdìpodobnost toho, ¾e vybereme \uv{¹patnou} -hranu le¾ící v~minimálním øezu, postupnì rostla z~poèáteèních $2/n$ a¾ po obrovské -$2/3$ v~poslední iteraci (pro $\ell=2$). Pomù¾e tedy zastavit kontrahování døíve -a~pøejít na~spolehlivìj¹í zpùsob hledání øezu. +Předchozí prostinký algoritmus můžeme jeÅ¡tě podstatně vylepÅ¡it. +VÅ¡imněme si, že během kontrahování hran pravděpodobnost toho, že vybereme \uv{Å¡patnou} +hranu ležící v~minimálním řezu, postupně rostla z~počátečních $2/n$ až po obrovské +$2/3$ v~poslední iteraci (pro $\ell=2$). Pomůže tedy zastavit kontrahování dříve +a~přejít na~spolehlivější způsob hledání řezu. -Pokud zvolíme $\ell=\lceil n/\sqrt2 +1\rceil$, pak øez~$C$ pøe¾ije kontrahování -s~pravdìpodobností alespoò +Pokud zvolíme $\ell=\lceil n/\sqrt2 +1\rceil$, pak řez~$C$ přežije kontrahování +s~pravděpodobností alespoň $$ {\ell\cdot (\ell-1) \over n\cdot (n-1)} \ge {(n/\sqrt2+1)\cdot n/\sqrt2 \over n\cdot (n-1)} @@ -107,70 +107,70 @@ $$ \ge {1\over 2}. $$ -Jako onen spolehlivìj¹í zpùsob hledání øezu následnì zavoláme stejný algoritmus -rekurzivnì, pøièem¾ jak kontrakci, tak rekurzi provedeme dvakrát a z~obou -nalezených øezù vybereme ten men¹í, èím¾ pravdìpodobnost chyby sní¾íme. +Jako onen spolehlivější způsob hledání řezu následně zavoláme stejný algoritmus +rekurzivně, přičemž jak kontrakci, tak rekurzi provedeme dvakrát a z~obou +nalezených řezů vybereme ten menší, čímž pravděpodobnost chyby snížíme. -Hotový algoritmus bude vypadat následovnì: +Hotový algoritmus bude vypadat následovně: \s{Algoritmus} $\hbox{\sc MinCut}(G)$: \algo -\:Pokud $n<7$, najdeme minimální øez hrubou silou. -\:$\ell\leftarrow \lceil n/\sqrt 2 + 1 \rceil$.\foot{To je ménì ne¾~$n$, kdykoliv $n\ge 7$.} +\:Pokud $n<7$, najdeme minimální řez hrubou silou. +\:$\ell\leftarrow \lceil n/\sqrt 2 + 1 \rceil$.\foot{To je méně než~$n$, kdykoliv $n\ge 7$.} \:$C_1 \leftarrow \hbox{\sc MinCut}(\hbox{\sc Contract}(G,\ell))$. \:$C_2 \leftarrow \hbox{\sc MinCut}(\hbox{\sc Contract}(G,\ell))$. -\:Vrátíme men¹í z~øezù $C_1$, $C_2$. +\:Vrátíme menší z~řezů $C_1$, $C_2$. \endalgo -Jakou bude mít tento algoritmus èasovou slo¾itost? Nejprve odhadnìme hloubku -rekurze: v~ka¾dém kroku se velikost vstupu zmen¹í pøibli¾nì $\sqrt 2$-krát, tak¾e strom -rekurze bude mít hloubku $\O(\log n)$. Na~$i$-té hladinì zpracováváme $2^i$ -podproblémù velikosti $n/2^{i/2}$. Pøi výpoètu ka¾dého podproblému voláme -dvakrát proceduru {\sc Contract}, která spotøebuje èas $\O((n/2^{i/2})^2) -= \O(n^2/2^i)$. Souèet pøes celou hladinu tedy èiní $\O(n^2)$ a pøes v¹echny -hladiny $\O(n^2\log n)$. Oproti pùvodnímu kontrakènímu algoritmu jsme si tedy -moc nepohor¹ili. - -Zbývá spoèítat, s~jakou pravdìpodobností algoritmus skuteènì nalezne minimální øez. -Oznaème $p_i$ pravdìpodobnost, ¾e algoritmus na~$i$-té hladinì stromu -rekurze (poèítáno od~nejhlub¹í, nulté hladiny) vydá správný výsledek -pøíslu¹ného podproblému. Jistì je $p_0=1$ a platí rekurence -$p_i \ge 1 - (1 - 1/2 \cdot p_{i-1})^2$. Uva¾ujme posloupnost $g_i$, pro kterou -jsou tyto nerovnosti splnìny jako rovnosti, a~v¹imnìme si, ¾e $p_i\ge g_i$. -Víme tedy, ¾e $g_0=1$ a $g_i = 1-(1-1/2\cdot g_{i-1})^2 = g_{i-1} - g_{i-1}^2/4$. - -Nyní zavedeme substituci $z_i = 4/g_i - 1$, èili $g_i=4/(z_i+1)$, a~tak získáme +Jakou bude mít tento algoritmus časovou složitost? Nejprve odhadněme hloubku +rekurze: v~každém kroku se velikost vstupu zmenší přibližně $\sqrt 2$-krát, takže strom +rekurze bude mít hloubku $\O(\log n)$. Na~$i$-té hladině zpracováváme $2^i$ +podproblémů velikosti $n/2^{i/2}$. Při výpočtu každého podproblému voláme +dvakrát proceduru {\sc Contract}, která spotřebuje čas $\O((n/2^{i/2})^2) += \O(n^2/2^i)$. Součet přes celou hladinu tedy činí $\O(n^2)$ a přes vÅ¡echny +hladiny $\O(n^2\log n)$. Oproti původnímu kontrakčnímu algoritmu jsme si tedy +moc nepohorÅ¡ili. + +Zbývá spočítat, s~jakou pravděpodobností algoritmus skutečně nalezne minimální řez. +Označme $p_i$ pravděpodobnost, že algoritmus na~$i$-té hladině stromu +rekurze (počítáno od~nejhlubší, nulté hladiny) vydá správný výsledek +přísluÅ¡ného podproblému. Jistě je $p_0=1$ a platí rekurence +$p_i \ge 1 - (1 - 1/2 \cdot p_{i-1})^2$. Uvažujme posloupnost $g_i$, pro kterou +jsou tyto nerovnosti splněny jako rovnosti, a~vÅ¡imněme si, že $p_i\ge g_i$. +Víme tedy, že $g_0=1$ a $g_i = 1-(1-1/2\cdot g_{i-1})^2 = g_{i-1} - g_{i-1}^2/4$. + +Nyní zavedeme substituci $z_i = 4/g_i - 1$, čili $g_i=4/(z_i+1)$, a~tak získáme novou rekurenci pro~$z_i$: $$ {4 \over z_i+1} = {4\over z_{i-1}+1} - {4\over (z_{i-1}+1)^2}, $$ -kterou u¾ mù¾eme snadno upravovat: +kterou už můžeme snadno upravovat: $$\eqalign{ {1\over z_i+1} &= {z_{i-1} \over (z_{i-1}+1)^2}, \cr z_i+1 &= {z_{i-1}^2 + 2z_{i-1} + 1 \over z_{i-1}}, \cr z_i+1 &= z_{i-1} + 2 + {1\over z_{i-1}}. \cr }$$ -Jeliko¾ $z_0=3$, a~tím pádem $z_i\ge 3$ pro v¹echna~$i$, získáme z~poslední -rovnosti vztah $z_i \le z_{i-1} + 2$, a~tudí¾ $z_i \le 2i+3$. -Zpìtnou substitucí obdr¾íme $g_i \ge 4/(2i+4)$, tedy $p_i \ge g_i = \Omega(1/i)$. +Jelikož $z_0=3$, a~tím pádem $z_i\ge 3$ pro vÅ¡echna~$i$, získáme z~poslední +rovnosti vztah $z_i \le z_{i-1} + 2$, a~tudíž $z_i \le 2i+3$. +Zpětnou substitucí obdržíme $g_i \ge 4/(2i+4)$, tedy $p_i \ge g_i = \Omega(1/i)$. -Nyní si staèí vzpomenout, ¾e hloubka rekurze èiní $\O(\log n)$, a ihned získáme -odhad pro pravdìpodobnost správného výsledku $\Omega(1/\log n)$. Ná¹ algoritmus -tedy staèí ziterovat $\O(\log^2 n)$-krát, abychom pravdìpodobnost chyby stlaèili -pod pøevrácenou hodnotu polynomu. Dokázali jsme následující vìtu: +Nyní si stačí vzpomenout, že hloubka rekurze činí $\O(\log n)$, a ihned získáme +odhad pro pravděpodobnost správného výsledku $\Omega(1/\log n)$. Náš algoritmus +tedy stačí ziterovat $\O(\log^2 n)$-krát, abychom pravděpodobnost chyby stlačili +pod převrácenou hodnotu polynomu. Dokázali jsme následující větu: -\s{Vìta:} Iterováním algoritmu {\sc MinCut} nalezneme minimální øez v~neohodnoceném -neorientovaném grafu v~èase $\O(n^2\log^3 n)$ s~pravdìpodobností chyby $\O(1/n^c)$ +\s{Věta:} Iterováním algoritmu {\sc MinCut} nalezneme minimální řez v~neohodnoceném +neorientovaném grafu v~čase $\O(n^2\log^3 n)$ s~pravděpodobností chyby $\O(1/n^c)$ pro libovolnou konstantu $c>0$. -\h{Cvièení} +\h{Cvičení} \numlist\ndotted -\:Zvolte lep¹í reprezentaci grafu, abyste prostorovou slo¾itost sní¾ili z~$\Theta(n^2)$ na~$\O(m)$. - Mù¾e se tím zmen¹it èasová slo¾itost? -\:Doka¾te, ¾e z~na¹eho rozboru pravdìpodobnosti chyby plyne, ¾e v~ka¾dém grafu je nejvý¹e $\O(n^2)$ - minimálních øezù. -\:Uka¾te, jak algoritmus upravit pro grafy s~ohodnocenými hranami. +\:Zvolte lepší reprezentaci grafu, abyste prostorovou složitost snížili z~$\Theta(n^2)$ na~$\O(m)$. + Může se tím zmenÅ¡it časová složitost? +\:Dokažte, že z~naÅ¡eho rozboru pravděpodobnosti chyby plyne, že v~každém grafu je nejvýše $\O(n^2)$ + minimálních řezů. +\:Ukažte, jak algoritmus upravit pro grafy s~ohodnocenými hranami. \endlist \references diff --git a/13-dijkstra/13-dijkstra.tex b/13-dijkstra/13-dijkstra.tex index d954cfd..48b28a4 100644 --- a/13-dijkstra/13-dijkstra.tex +++ b/13-dijkstra/13-dijkstra.tex @@ -1,679 +1,679 @@ \input ../sgr.tex -\prednaska{13}{Nejkrat¹í cesty}{} +\prednaska{13}{NejkratĹĄĂ­ cesty}{} \def\ppsp{1-1} \def\sssp{1-$n$} \def\apsp{$n$-$n$} \def\astar{A\kern-0.15em *} -Problém hledání nejkrat¹í cesty v~(obvykle ohodnoceném orientovaném) grafu -provází teorii grafových algoritmù od~samých poèátkù. Základní algoritmy -pro hledání cest jsou nedílnou souèástí základních kursù programování -a algoritmù, my se budeme vìnovat zejména rùzným jejich vylep¹ením. +ProblĂŠm hledĂĄnĂ­ nejkratĹĄĂ­ cesty v~(obvykle ohodnocenĂŠm orientovanĂŠm) grafu +provĂĄzĂ­ teorii grafovĂ˝ch algoritmĹŻ od~samĂ˝ch počátkĹŻ. ZĂĄkladnĂ­ algoritmy +pro hledĂĄnĂ­ cest jsou nedĂ­lnou součástĂ­ zĂĄkladnĂ­ch kursĹŻ programovĂĄnĂ­ +a algoritmĹŻ, my se budeme věnovat zejmĂŠna rĹŻznĂ˝m jejich vylepĹĄenĂ­m. -Uva¾ujme tedy nìjaký orientovaný graf, jeho¾ ka¾dá hrana~$e$ je opatøena -{\I délkou} $\ell(e)\in{\bb R}$. Mno¾inì hran (tøeba sledu nebo cestì) -pak pøiøadíme délku rovnou souètu délek jednotlivých hran. +UvaĹžujme tedy nějakĂ˝ orientovanĂ˝ graf, jehoĹž kaĹždĂĄ hrana~$e$ je opatřena +{\I dĂŠlkou} $\ell(e)\in{\bb R}$. MnoĹžině hran (třeba sledu nebo cestě) +pak přiřadĂ­me dĂŠlku rovnou součtu dĂŠlek jednotlivĂ˝ch hran. -Pro vrcholy $u,v$ definujeme jejich {\I vzdálenost} $d(u,v)$ jako nejmen¹í -mo¾nou délku cesty z~$u$ do~$v$ (jeliko¾ cest je v~grafu koneènì mnoho, -minimum v¾dy existuje). Pokud z~$u$ do~$v$ ¾ádná cesta nevede, polo¾íme +Pro vrcholy $u,v$ definujeme jejich {\I vzdĂĄlenost} $d(u,v)$ jako nejmenĹĄĂ­ +moĹžnou dĂŠlku cesty z~$u$ do~$v$ (jelikoĹž cest je v~grafu konečně mnoho, +minimum vĹždy existuje). Pokud z~$u$ do~$v$ ŞådnĂĄ cesta nevede, poloŞíme $d(u,v) := \infty$. -Obvykle se studují následující tøi problémy: +Obvykle se studujĂ­ nĂĄsledujĂ­cĂ­ tři problĂŠmy: \itemize\ibull -\:{\bo 1-1} neboli {\bo P2PSP} (Point to Point Shortest Path) -- chceme nalézt nejkrat¹í - cestu z~daného vrcholu~$u$ do~daného vrcholu~$v$. (Pokud je nejkrat¹ích cest - více, tak libovolnou z~nich.) -\:{\bo 1-n} neboli {\bo SSSP} (Single Source Shortest Paths) -- pro daný vrchol~$u$ chceme - nalézt nejkrat¹í cesty do~v¹ech ostatních vrcholù. -\:{\bo n-n} neboli {\bo APSP} (All Pairs Shortest Paths) -- zajímají nás nejkrat¹í cesty - mezi v¹emi dvojicemi vrcholù. +\:{\bo 1-1} neboli {\bo P2PSP} (Point to Point Shortest Path) -- chceme nalĂŠzt nejkratĹĄĂ­ + cestu z~danĂŠho vrcholu~$u$ do~danĂŠho vrcholu~$v$. (Pokud je nejkratĹĄĂ­ch cest + vĂ­ce, tak libovolnou z~nich.) +\:{\bo 1-n} neboli {\bo SSSP} (Single Source Shortest Paths) -- pro danĂ˝ vrchol~$u$ chceme + nalĂŠzt nejkratĹĄĂ­ cesty do~vĹĄech ostatnĂ­ch vrcholĹŻ. +\:{\bo n-n} neboli {\bo APSP} (All Pairs Shortest Paths) -- zajĂ­majĂ­ nĂĄs nejkratĹĄĂ­ cesty + mezi vĹĄemi dvojicemi vrcholĹŻ. \endlist -Pøekvapivì, tak obecnì, jak jsme si uvedené problémy definovali, je neumíme -øe¹it v~polynomiálním èase: pro grafy, které mohou obsahovat hrany záporných -délek bez jakýchkoliv omezení, je toti¾ hledání nejkrat¹í cesty NP-tì¾ké -(lze na~nìj snadno pøevést existenci hamiltonovské cesty). V¹echny známé -polynomiální algoritmy toti¾ místo nejkrat¹í cesty hledají nejkrat¹í sled --- nijak nekontrolují, zda cesta neprojde jedním vrcholem vícekrát. - -Na¹tìstí pro nás je to v~grafech bez cyklù záporné délky toté¾: pokud se -v~nalezeném sledu vyskytne cyklus, mù¾eme jej \uv{vystøihnout} a tím získat -sled, který není del¹í a~který má ménì hran. Ka¾dý nejkrat¹í sled tak -mù¾eme upravit na~stejnì dlouhou cestu. -V~grafech bez záporných cyklù je tedy jedno, zda hledáme sled nebo cestu; -naopak vyskytne-li se záporný cyklus dosa¾itelný z~poèáteèního vrcholu, -nejkrat¹í sled ani neexistuje. - -Navíc se nám bude hodit, ¾e ka¾dý prefix nejkrat¹í cesty je opìt nejkrat¹í -cesta. Jinými slovy pokud nìkterá z~nejkrat¹ích cest z~$u$ do~$v$ vede -pøes nìjaký vrchol~$w$, pak její èást z~$u$ do~$w$ je jednou z~nejkrat¹ích -cest z~$u$ do~$w$. (V~opaèném pøípadì bychom mohli úsek $u\ldots w$ vymìnit za~krat¹í.) - -Díky této {\I prefixové vlastnosti} mù¾eme pro ka¾dý vrchol~$u$ sestrojit jeho {\I strom -nejkrat¹ích cest}~${\cal T}(u)$. To je nìjaký podgraf grafu~$G$, který má tvar -stromu zakoøenìného v~$u$ a orientovaného smìrem od~koøene, a~platí pro nìj, ¾e -pro ka¾dý vrchol~$v$ je (jediná) cesta z~$u$ do~$v$ v~tomto stromu jednou -z~nejkrat¹ích cest z~$u$ do~$v$ v~pùvodním grafu. - -\s{Pozorování:} Strom nejkrat¹ích cest v¾dy existuje. +Překvapivě, tak obecně, jak jsme si uvedenĂŠ problĂŠmy definovali, je neumĂ­me +řeĹĄit v~polynomiĂĄlnĂ­m čase: pro grafy, kterĂŠ mohou obsahovat hrany zĂĄpornĂ˝ch +dĂŠlek bez jakĂ˝chkoliv omezenĂ­, je totiĹž hledĂĄnĂ­ nejkratĹĄĂ­ cesty NP-těžkĂŠ +(lze na~něj snadno převĂŠst existenci hamiltonovskĂŠ cesty). VĹĄechny znĂĄmĂŠ +polynomiĂĄlnĂ­ algoritmy totiĹž mĂ­sto nejkratĹĄĂ­ cesty hledajĂ­ nejkratĹĄĂ­ sled +-- nijak nekontrolujĂ­, zda cesta neprojde jednĂ­m vrcholem vĂ­cekrĂĄt. + +NaĹĄtěstĂ­ pro nĂĄs je to v~grafech bez cyklĹŻ zĂĄpornĂŠ dĂŠlky totĂŠĹž: pokud se +v~nalezenĂŠm sledu vyskytne cyklus, mĹŻĹžeme jej \uv{vystřihnout} a tĂ­m zĂ­skat +sled, kterĂ˝ nenĂ­ delĹĄĂ­ a~kterĂ˝ mĂĄ mĂŠně hran. KaĹždĂ˝ nejkratĹĄĂ­ sled tak +mĹŻĹžeme upravit na~stejně dlouhou cestu. +V~grafech bez zĂĄpornĂ˝ch cyklĹŻ je tedy jedno, zda hledĂĄme sled nebo cestu; +naopak vyskytne-li se zĂĄpornĂ˝ cyklus dosaĹžitelnĂ˝ z~počátečnĂ­ho vrcholu, +nejkratĹĄĂ­ sled ani neexistuje. + +NavĂ­c se nĂĄm bude hodit, Ĺže kaĹždĂ˝ prefix nejkratĹĄĂ­ cesty je opět nejkratĹĄĂ­ +cesta. JinĂ˝mi slovy pokud některĂĄ z~nejkratĹĄĂ­ch cest z~$u$ do~$v$ vede +přes nějakĂ˝ vrchol~$w$, pak jejĂ­ část z~$u$ do~$w$ je jednou z~nejkratĹĄĂ­ch +cest z~$u$ do~$w$. (V~opačnĂŠm případě bychom mohli Ăşsek $u\ldots w$ vyměnit za~kratĹĄĂ­.) + +DĂ­ky tĂŠto {\I prefixovĂŠ vlastnosti} mĹŻĹžeme pro kaĹždĂ˝ vrchol~$u$ sestrojit jeho {\I strom +nejkratĹĄĂ­ch cest}~${\cal T}(u)$. To je nějakĂ˝ podgraf grafu~$G$, kterĂ˝ mĂĄ tvar +stromu zakořeněnĂŠho v~$u$ a orientovanĂŠho směrem od~kořene, a~platĂ­ pro něj, Ĺže +pro kaĹždĂ˝ vrchol~$v$ je (jedinĂĄ) cesta z~$u$ do~$v$ v~tomto stromu jednou +z~nejkratĹĄĂ­ch cest z~$u$ do~$v$ v~pĹŻvodnĂ­m grafu. + +\s{PozorovĂĄnĂ­:} Strom nejkratĹĄĂ­ch cest vĹždy existuje. \proof -Nech» $u=v_1,\ldots,v_n$ jsou v¹echny vrcholy grafu~$G$. Indukcí budeme -dokazovat, ¾e pro ka¾dé~$i$ existuje strom~${\cal T}_i$, v~nìm¾ se nacházejí nejkrat¹í -cesty z~vrcholu~$u$ do vrcholù $v_1,\ldots,v_i$. Pro $i=1$ staèí uvá¾it -strom obsahující jediný vrchol~$u$. Ze~stromu ${\cal T}_{i-1}$ pak vyrobíme -strom ${\cal T}_i$ takto: Nalezneme v~$G$ nejkrat¹í cestu z~$u$ do~$v_i$ -a oznaèíme~$z$ poslední vrchol na~této cestì, který se je¹tì vyskytuje v~${\cal T}_{i-1}$. -Úsek nejkrat¹í cesty od~$z$ do~$v_i$ pak pøidáme do~${\cal T}_{i-1}$ -a díky prefixové vlastnosti bude i cesta z~$u$ do~$v_i$ v~novém stromu -nejkrat¹í. +NechĹĽ $u=v_1,\ldots,v_n$ jsou vĹĄechny vrcholy grafu~$G$. IndukcĂ­ budeme +dokazovat, Ĺže pro kaĹždĂŠ~$i$ existuje strom~${\cal T}_i$, v~němĹž se nachĂĄzejĂ­ nejkratĹĄĂ­ +cesty z~vrcholu~$u$ do vrcholĹŻ $v_1,\ldots,v_i$. Pro $i=1$ stačí uvĂĄĹžit +strom obsahujĂ­cĂ­ jedinĂ˝ vrchol~$u$. Ze~stromu ${\cal T}_{i-1}$ pak vyrobĂ­me +strom ${\cal T}_i$ takto: Nalezneme v~$G$ nejkratĹĄĂ­ cestu z~$u$ do~$v_i$ +a označíme~$z$ poslednĂ­ vrchol na~tĂŠto cestě, kterĂ˝ se jeĹĄtě vyskytuje v~${\cal T}_{i-1}$. +Úsek nejkratĹĄĂ­ cesty od~$z$ do~$v_i$ pak přidĂĄme do~${\cal T}_{i-1}$ +a dĂ­ky prefixovĂŠ vlastnosti bude i cesta z~$u$ do~$v_i$ v~novĂŠm stromu +nejkratĹĄĂ­. \qed -Zbývá se dohodnout, v~jakém tvaru mají na¹e algoritmy vydávat výsledek. -U~problémù typu \ppsp{} je nejjednodu¹¹í vypsat celou cestu, u~\sssp{} mù¾eme jako výstup -vydat strom nejkrat¹ích cest z~daného poèátku (v¹imnìte si, ¾e staèí -uvést pøedchùdce ka¾dého vrcholu), u~\apsp{} vydáme strom nejkrat¹ích cest -pro ka¾dý ze~zdrojových vrcholù. +ZbĂ˝vĂĄ se dohodnout, v~jakĂŠm tvaru majĂ­ naĹĄe algoritmy vydĂĄvat vĂ˝sledek. +U~problĂŠmĹŻ typu \ppsp{} je nejjednoduĹĄĹĄĂ­ vypsat celou cestu, u~\sssp{} mĹŻĹžeme jako vĂ˝stup +vydat strom nejkratĹĄĂ­ch cest z~danĂŠho počátku (vĹĄimněte si, Ĺže stačí +uvĂŠst předchĹŻdce kaĹždĂŠho vrcholu), u~\apsp{} vydĂĄme strom nejkratĹĄĂ­ch cest +pro kaĹždĂ˝ ze~zdrojovĂ˝ch vrcholĹŻ. -Èasto se ov¹em uká¾e, ¾e podstatná èást problému se skrývá v~samotném -výpoètu vzdáleností a sestrojení pøedchùdcù je triviálním roz¹íøením algoritmu. -Budeme tedy obvykle jen poèítat vzdálenosti a samotnou rekonstrukci cest -ponecháme ètenáøi jako snadné cvièení. +Často se ovĹĄem ukĂĄĹže, Ĺže podstatnĂĄ část problĂŠmu se skrĂ˝vĂĄ v~samotnĂŠm +vĂ˝počtu vzdĂĄlenostĂ­ a sestrojenĂ­ předchĹŻdcĹŻ je triviĂĄlnĂ­m rozšířenĂ­m algoritmu. +Budeme tedy obvykle jen počítat vzdĂĄlenosti a samotnou rekonstrukci cest +ponechĂĄme čtenáři jako snadnĂŠ cvičenĂ­. -\h{Relaxaèní algoritmus} +\h{RelaxačnĂ­ algoritmus} -Zaènìme problémem \sssp{} a oznaème~$u$ výchozí vrchol. Vìt¹ina známých -algoritmù funguje tak, ¾e pro ka¾dý vrchol~$v$ udr¾ují ohodnocení $h(v)$, -které v~ka¾dém okam¾iku odpovídá délce nìjakého sledu z~$u$ do~$v$. Postupnì -toto ohodnocení upravují, a¾ se z~nìj stane vzdálenost $d(u,v)$ a algoritmus -se mù¾e zastavit. +Začněme problĂŠmem \sssp{} a označme~$u$ vĂ˝chozĂ­ vrchol. VětĹĄina znĂĄmĂ˝ch +algoritmĹŻ funguje tak, Ĺže pro kaĹždĂ˝ vrchol~$v$ udrĹžujĂ­ ohodnocenĂ­ $h(v)$, +kterĂŠ v~kaĹždĂŠm okamĹžiku odpovĂ­dĂĄ dĂŠlce nějakĂŠho sledu z~$u$ do~$v$. Postupně +toto ohodnocenĂ­ upravujĂ­, aĹž se z~něj stane vzdĂĄlenost $d(u,v)$ a algoritmus +se mĹŻĹže zastavit. -Vhodnou operací pro vylep¹ování ohodnocení je takzvaná {\I relaxace.} -Vybereme si nìjaký vrchol~$v$ a pro v¹echny jeho sousedy~$w$ spoèítáme -$h(v) + \ell(v,w)$, tedy délku sledu, který vznikne roz¹íøením aktuálního -sledu do~$v$ o~hranu $(v,w)$. Pokud je tato hodnota men¹í ne¾~$h(w)$, -tak jí $h(w)$ pøepí¹eme. +Vhodnou operacĂ­ pro vylepĹĄovĂĄnĂ­ ohodnocenĂ­ je takzvanĂĄ {\I relaxace.} +Vybereme si nějakĂ˝ vrchol~$v$ a pro vĹĄechny jeho sousedy~$w$ spočítĂĄme +$h(v) + \ell(v,w)$, tedy dĂŠlku sledu, kterĂ˝ vznikne rozšířenĂ­m aktuĂĄlnĂ­ho +sledu do~$v$ o~hranu $(v,w)$. Pokud je tato hodnota menĹĄĂ­ neĹž~$h(w)$, +tak jĂ­ $h(w)$ přepĂ­ĹĄeme. -Abychom zabránili opakovaným relaxacím tého¾ vrcholu, které nic nezmìní, -budeme rozli¹ovat tøi stavy vrcholù: {\I nevidìn} (je¹tì jsme ho nenav¹tívili), -{\I otevøen} (zmìnilo se ohodnocení, èasem chceme relaxovat) a {\I uzavøen} -(u¾ jsme relaxovali a není potøeba znovu). +Abychom zabrĂĄnili opakovanĂ˝m relaxacĂ­m tĂŠhoĹž vrcholu, kterĂŠ nic nezměnĂ­, +budeme rozliĹĄovat tři stavy vrcholĹŻ: {\I neviděn} (jeĹĄtě jsme ho nenavĹĄtĂ­vili), +{\I otevřen} (změnilo se ohodnocenĂ­, časem chceme relaxovat) a {\I uzavřen} +(uĹž jsme relaxovali a nenĂ­ potřeba znovu). -Ná¹ algoritmus bude fungovat následovnì: +NĂĄĹĄ algoritmus bude fungovat nĂĄsledovně: \algo \:$h(*)\leftarrow \infty$, $h(u)\leftarrow 0$. -\:$\(*)\leftarrow\$, $\(u)\leftarrow\$. -\:Dokud existují otevøené vrcholy, opakujeme: -\::$v\leftarrow\hbox{libovolný otevøený vrchol}$. -\::$\(v)\leftarrow\$. +\:$\(*)\leftarrow\$, $\(u)\leftarrow\$. +\:Dokud existujĂ­ otevřenĂŠ vrcholy, opakujeme: +\::$v\leftarrow\hbox{libovolnĂ˝ otevřenĂ˝ vrchol}$. +\::$\(v)\leftarrow\$. \::Relaxujeme~$v$: -\:::Pro v¹echny hrany $vw$ opakujeme: +\:::Pro vĹĄechny hrany $vw$ opakujeme: \::::Je-li $h(w) > h(v) + \ell(v,w)$: \:::::$h(w)\leftarrow h(v) + \ell(v,w)$. -\:::::$\(w)\leftarrow\$. -\:Vrátíme výsledek $d(u,v)=h(v)$ pro v¹echna~$v$. +\:::::$\(w)\leftarrow\$. +\:VrĂĄtĂ­me vĂ˝sledek $d(u,v)=h(v)$ pro vĹĄechna~$v$. \endalgo -Podobnì jako u~minimálních koster, i zde se jedná o~meta-algoritmus, proto¾e -v~kroku~4 nespecifikuje, který z~otevøených vrcholù vybírá. Pøesto -ale mù¾eme dokázat nìkolik zajímavých tvrzení, která na~konkrétním zpùsobu -výbìru nezávisejí. +Podobně jako u~minimĂĄlnĂ­ch koster, i zde se jednĂĄ o~meta-algoritmus, protoĹže +v~kroku~4 nespecifikuje, kterĂ˝ z~otevřenĂ˝ch vrcholĹŻ vybĂ­rĂĄ. Přesto +ale mĹŻĹžeme dokĂĄzat několik zajĂ­mavĂ˝ch tvrzenĂ­, kterĂĄ na~konkrĂŠtnĂ­m zpĹŻsobu +vĂ˝běru nezĂĄvisejĂ­. -\s{Vìta:} Spustíme-li meta-algoritmus na graf bez záporných cyklù, pak: +\s{Věta:} SpustĂ­me-li meta-algoritmus na graf bez zĂĄpornĂ˝ch cyklĹŻ, pak: \numlist\nparen -\:Ohodnocení $h(v)$ v¾dy odpovídá délce nìjakého sledu z~$u$ do~$v$. -\:$h(v)$ dokonce odpovídá délce nìjaké cesty z~$u$ do~$v$. -\:Algoritmus se v¾dy zastaví. -\:Po zastavení jsou oznaèeny jako uzavøené právì ty vrcholy, které jsou dosa¾itelné z~$u$. -\:Po zastavení mají koneèné~$h(v)$ právì v¹echny uzavøené vrcholy. -\:Pro ka¾dý dosa¾itelný vrchol je na~konci $h(v)$ rovno $d(u,v)$. +\:OhodnocenĂ­ $h(v)$ vĹždy odpovĂ­dĂĄ dĂŠlce nějakĂŠho sledu z~$u$ do~$v$. +\:$h(v)$ dokonce odpovĂ­dĂĄ dĂŠlce nějakĂŠ cesty z~$u$ do~$v$. +\:Algoritmus se vĹždy zastavĂ­. +\:Po zastavenĂ­ jsou označeny jako uzavřenĂŠ prĂĄvě ty vrcholy, kterĂŠ jsou dosaĹžitelnĂŠ z~$u$. +\:Po zastavenĂ­ majĂ­ konečnĂŠ~$h(v)$ prĂĄvě vĹĄechny uzavřenĂŠ vrcholy. +\:Pro kaĹždĂ˝ dosaĹžitelnĂ˝ vrchol je na~konci $h(v)$ rovno $d(u,v)$. \endlist \proof \numlist\nparen -\:Doká¾eme indukcí podle poètu krokù algoritmu. -\:Staèí rozmyslet, v~jaké situaci by vytvoøený sled mohl obsahovat cyklus. -\:Cest, a~tím pádem i mo¾ných hodnot~$h(v)$ pro ka¾dý~$v$, je koneènì mnoho. -\:Implikace $\Rightarrow$ je triviální, pro $\Leftarrow$ staèí uvá¾it neuzavøený vrchol, - který je dosa¾itelný z~$u$ cestou o~co nejmen¹ím poètu hran. -\:$h(v)$ nastavujeme na~koneènou hodnotu právì v~okam¾icích, kdy se vrchol stává otevøeným. - Ka¾dý otevøený vrchol je èasem uzavøen. +\:DokĂĄĹžeme indukcĂ­ podle počtu krokĹŻ algoritmu. +\:Stačí rozmyslet, v~jakĂŠ situaci by vytvořenĂ˝ sled mohl obsahovat cyklus. +\:Cest, a~tĂ­m pĂĄdem i moĹžnĂ˝ch hodnot~$h(v)$ pro kaĹždĂ˝~$v$, je konečně mnoho. +\:Implikace $\Rightarrow$ je triviĂĄlnĂ­, pro $\Leftarrow$ stačí uvĂĄĹžit neuzavřenĂ˝ vrchol, + kterĂ˝ je dosaĹžitelnĂ˝ z~$u$ cestou o~co nejmenĹĄĂ­m počtu hran. +\:$h(v)$ nastavujeme na~konečnou hodnotu prĂĄvě v~okamĹžicĂ­ch, kdy se vrchol stĂĄvĂĄ otevřenĂ˝m. + KaĹždĂ˝ otevřenĂ˝ vrchol je časem uzavřen. \:Kdyby tomu tak nebylo, - vyberme si ze~\uv{¹patných} vrcholù~$v$ takový, pro nìj¾ obsahuje nejkrat¹í cesta z~$u$ do~$v$ - nejmen¹í mo¾ný poèet hran. Vrchol~$v$ je zajisté rùzný od~$u$, tak¾e má na~této cestì nìjakého - pøedchùdce~$w$. Pøitom~$w$ u¾ musí být ohodnocen správnì a relaxace, která mu toto ohodnocení - nastavila, ho musela prohlásit za~otevøený. Jen¾e ka¾dý otevøený vrchol je pozdìji uzavøen, - tak¾e~$w$ poté musel být je¹tì alespoò jednou relaxován, co¾ muselo sní¾it~$h(v)$ na správnou - vzdálenost. + vyberme si ze~\uv{ĹĄpatnĂ˝ch} vrcholĹŻ~$v$ takovĂ˝, pro nějĹž obsahuje nejkratĹĄĂ­ cesta z~$u$ do~$v$ + nejmenĹĄĂ­ moĹžnĂ˝ počet hran. Vrchol~$v$ je zajistĂŠ rĹŻznĂ˝ od~$u$, takĹže mĂĄ na~tĂŠto cestě nějakĂŠho + předchĹŻdce~$w$. Přitom~$w$ uĹž musĂ­ bĂ˝t ohodnocen sprĂĄvně a relaxace, kterĂĄ mu toto ohodnocenĂ­ + nastavila, ho musela prohlĂĄsit za~otevřenĂ˝. JenĹže kaĹždĂ˝ otevřenĂ˝ vrchol je později uzavřen, + takĹže~$w$ potĂŠ musel bĂ˝t jeĹĄtě alespoň jednou relaxovĂĄn, coĹž muselo snĂ­Ĺžit~$h(v)$ na sprĂĄvnou + vzdĂĄlenost. \qeditem \endlist -\>Dokázali jsme tedy, ¾e meta-algoritmus pro libovolnou implementaci kroku~4 -spoèítá správné vzdálenosti. +\>DokĂĄzali jsme tedy, Ĺže meta-algoritmus pro libovolnou implementaci kroku~4 +spočítĂĄ sprĂĄvnĂŠ vzdĂĄlenosti. \medskip -\s{Cvièení:} +\s{CvičenĂ­:} \itemize\ibull -\:Nech» do algoritmu doplníme udr¾ování pøedchùdcù tak, ¾e v~kroku~9 - pøenastavíme pøedchùdce vrcholu~$w$ na vrchol~$v$. Doka¾te, ¾e pøedchùdci - dosa¾itelných vrcholù budou tvoøit strom a ¾e tento strom bude stromem - nejkrat¹ích cest z~vrcholu~$u$. -\:Doka¾te, ¾e pro graf, v~nìm¾ je alespoò jeden záporný cyklus dosa¾itelný - z~poèáteèního vrcholu, se algoritmus nezastaví a ohodnocení v¹ech vrcholù - na cyklu postupnì klesnou libovolnì hluboko. Nedosa¾itelné záporné cykly - chod algoritmu samozøejmì nijak neovlivní. +\:NechĹĽ do algoritmu doplnĂ­me udrĹžovĂĄnĂ­ předchĹŻdcĹŻ tak, Ĺže v~kroku~9 + přenastavĂ­me předchĹŻdce vrcholu~$w$ na vrchol~$v$. DokaĹžte, Ĺže předchĹŻdci + dosaĹžitelnĂ˝ch vrcholĹŻ budou tvořit strom a Ĺže tento strom bude stromem + nejkratĹĄĂ­ch cest z~vrcholu~$u$. +\:DokaĹžte, Ĺže pro graf, v~němĹž je alespoň jeden zĂĄpornĂ˝ cyklus dosaĹžitelnĂ˝ + z~počátečnĂ­ho vrcholu, se algoritmus nezastavĂ­ a ohodnocenĂ­ vĹĄech vrcholĹŻ + na cyklu postupně klesnou libovolně hluboko. NedosaĹžitelnĂŠ zĂĄpornĂŠ cykly + chod algoritmu samozřejmě nijak neovlivnĂ­. \endlist -\h{Bellmanùv-Fordùv-Mooreùv algoritmus} +\h{BellmanĹŻv-FordĹŻv-MooreĹŻv algoritmus} -Bellman \cite{bellman:bfm}, Ford \cite{ford:bfm} a Moore objevili nezávisle na sobì algoritmus (øíkejme mu BFM), -který lze v~øeèi na¹eho meta-algoritmu formulovat takto: Otevøené vrcholy -udr¾ujeme ve~frontì (v¾dy relaxujeme vrchol na poèátku fronty, novì otevírané -zaøazujeme na~konec). Co toto pravidlo zpùsobí? +Bellman \cite{bellman:bfm}, Ford \cite{ford:bfm} a Moore objevili nezĂĄvisle na sobě algoritmus (říkejme mu BFM), +kterĂ˝ lze v~řeči naĹĄeho meta-algoritmu formulovat takto: OtevřenĂŠ vrcholy +udrĹžujeme ve~frontě (vĹždy relaxujeme vrchol na počátku fronty, nově otevĂ­ranĂŠ +zařazujeme na~konec). Co toto pravidlo zpĹŻsobĂ­? -\s{Vìta:} Èasová slo¾itost algoritmu~BFM èiní $\O(nm)$. +\s{Věta:} ČasovĂĄ sloĹžitost algoritmu~BFM činĂ­ $\O(nm)$. \proof -Bìh algoritmu rozdìlíme na~fáze. Nultá fáze sestává z~vlo¾ení vrcholu~$u$ -do~fronty. V~$(i+1)$-ní fázi relaxujeme ty vrcholy, které byly do~fronty -ulo¾eny bìhem $i$-té fáze. - -Jeliko¾ relaxace vrcholu trvá lineárnì se stupnìm vrcholu a ka¾dý vrchol -se dané fáze úèastní nejvý¹e jednou, trvá jedna fáze $\O(m)$. Zbývá ukázat, -¾e fází provedeme nejvý¹e~$n$. - -Indukcí doká¾eme, ¾e na konci $i$-té fáze je ka¾dé ohodnocení $h(v)$ shora omezeno -délkou nejkrat¹ího z~$uv$-sledù o~nejvý¹e~$i$ hranách. Pro $i=0$ to triviálnì -platí. Uva¾ujme nyní vrchol~$v$ na konci $(i+1)$-ní fáze a nìjaký nejkrat¹í $uv$-sled~$P$ -o~$i+1$ hranách. Oznaème $wv$ poslední hranu tohoto sledu a $P'$ sled bez této hrany, -který tedy má délku~$i$. Podle indukèního pøedpokladu je na konci $i$-té fáze -$h(w)\le \ell(P')$. Tuto hodnotu získalo $h(w)$ nejpozdìji v~$i$-té fázi, pøi tom jsme -vrchol~$w$ otevøeli, tak¾e jsme ho nejpozdìji v~$(i+1)$-ní fázi zavøeli a relaxovali. -Po této relaxaci je ov¹em $h(v)\le h(w)+\ell(w,v)\le \ell(P') + \ell(w,v) = \ell(P)$. +Běh algoritmu rozdělĂ­me na~fĂĄze. NultĂĄ fĂĄze sestĂĄvĂĄ z~vloĹženĂ­ vrcholu~$u$ +do~fronty. V~$(i+1)$-nĂ­ fĂĄzi relaxujeme ty vrcholy, kterĂŠ byly do~fronty +uloĹženy během $i$-tĂŠ fĂĄze. + +JelikoĹž relaxace vrcholu trvĂĄ lineĂĄrně se stupněm vrcholu a kaĹždĂ˝ vrchol +se danĂŠ fĂĄze účastnĂ­ nejvýťe jednou, trvĂĄ jedna fĂĄze $\O(m)$. ZbĂ˝vĂĄ ukĂĄzat, +Ĺže fĂĄzĂ­ provedeme nejvýťe~$n$. + +IndukcĂ­ dokĂĄĹžeme, Ĺže na konci $i$-tĂŠ fĂĄze je kaĹždĂŠ ohodnocenĂ­ $h(v)$ shora omezeno +dĂŠlkou nejkratĹĄĂ­ho z~$uv$-sledĹŻ o~nejvýťe~$i$ hranĂĄch. Pro $i=0$ to triviĂĄlně +platĂ­. UvaĹžujme nynĂ­ vrchol~$v$ na konci $(i+1)$-nĂ­ fĂĄze a nějakĂ˝ nejkratĹĄĂ­ $uv$-sled~$P$ +o~$i+1$ hranĂĄch. Označme $wv$ poslednĂ­ hranu tohoto sledu a $P'$ sled bez tĂŠto hrany, +kterĂ˝ tedy mĂĄ dĂŠlku~$i$. Podle indukčnĂ­ho předpokladu je na konci $i$-tĂŠ fĂĄze +$h(w)\le \ell(P')$. Tuto hodnotu zĂ­skalo $h(w)$ nejpozději v~$i$-tĂŠ fĂĄzi, při tom jsme +vrchol~$w$ otevřeli, takĹže jsme ho nejpozději v~$(i+1)$-nĂ­ fĂĄzi zavřeli a relaxovali. +Po tĂŠto relaxaci je ovĹĄem $h(v)\le h(w)+\ell(w,v)\le \ell(P') + \ell(w,v) = \ell(P)$. \qed -\s{Cvièení:} +\s{CvičenĂ­:} \itemize\ibull -\:Uka¾te, ¾e asymptoticky stejné èasové slo¾itosti by dosáhl algoritmus, - který by vrcholy oèísloval $v_1,\ldots,v_n$ a opakovanì by je v~tomto - poøadí relaxoval tak dlouho, dokud by se ohodnocení mìnila. -\:Jak algoritmus upravit, aby v~$i$-té fázi spoèítal minimální délky sledù - o~právì~$i$ hranách? -\:Jak lze algoritmus BFM vyu¾ít k~nalezení záporného cyklu? +\:UkaĹžte, Ĺže asymptoticky stejnĂŠ časovĂŠ sloĹžitosti by dosĂĄhl algoritmus, + kterĂ˝ by vrcholy očísloval $v_1,\ldots,v_n$ a opakovaně by je v~tomto + pořadĂ­ relaxoval tak dlouho, dokud by se ohodnocenĂ­ měnila. +\:Jak algoritmus upravit, aby v~$i$-tĂŠ fĂĄzi spočítal minimĂĄlnĂ­ dĂŠlky sledĹŻ + o~prĂĄvě~$i$ hranĂĄch? +\:Jak lze algoritmus BFM vyuŞít k~nalezenĂ­ zĂĄpornĂŠho cyklu? \endlist -\h{Dijkstrùv algoritmus} +\h{DijkstrĹŻv algoritmus} -Pokud jsou v¹echny délky hran nezáporné, mù¾eme pou¾ít efektivnìj¹í pravidlo -pro výbìr vrcholu navr¾ené Dijkstrou \cite{dijkstra:mstandpath}. To øíká, ¾e v¾dy relaxujeme ten z~otevøených -vrcholù, jeho¾ ohodnocení je nejmen¹í. +Pokud jsou vĹĄechny dĂŠlky hran nezĂĄpornĂŠ, mĹŻĹžeme pouŞít efektivnějĹĄĂ­ pravidlo +pro vĂ˝běr vrcholu navrĹženĂŠ Dijkstrou \cite{dijkstra:mstandpath}. To říkĂĄ, Ĺže vĹždy relaxujeme ten z~otevřenĂ˝ch +vrcholĹŻ, jehoĹž ohodnocenĂ­ je nejmenĹĄĂ­. -\s{Vìta:} Dijkstrùv algoritmus uzavírá vrcholy v~poøadí podle neklesající -vzdálenosti od~$u$ a ka¾dý dosa¾itelný vrchol uzavøe právì jednou. +\s{Věta:} DijkstrĹŻv algoritmus uzavĂ­rĂĄ vrcholy v~pořadĂ­ podle neklesajĂ­cĂ­ +vzdĂĄlenosti od~$u$ a kaĹždĂ˝ dosaĹžitelnĂ˝ vrchol uzavře prĂĄvě jednou. \proof -Indukcí doká¾eme, ¾e v~ka¾dém okam¾iku mají v¹echny uzavøené vrcholy ohodnocení -men¹í nebo rovné ohodnocením v¹ech otevøených vrcholù. Na~poèátku to jistì platí. -Nech» nyní uzavíráme vrchol~$v$ s~minimálním $h(v)$ mezi otevøenými. Bìhem jeho -relaxace nemù¾eme ¾ádnou hodnotu sní¾it pod~$h(v)$, jeliko¾ v~grafu s~nezápornými -hranami je $h(v) + \ell(v,w) \ge h(v)$. Hodnota zbývajících otevøených vrcholù -tedy neklesne pod hodnotu tohoto novì uzavøeného. Hodnoty døíve uzavøených vrcholù -se nemohou nijak zmìnit. +IndukcĂ­ dokĂĄĹžeme, Ĺže v~kaĹždĂŠm okamĹžiku majĂ­ vĹĄechny uzavřenĂŠ vrcholy ohodnocenĂ­ +menĹĄĂ­ nebo rovnĂŠ ohodnocenĂ­m vĹĄech otevřenĂ˝ch vrcholĹŻ. Na~počátku to jistě platĂ­. +NechĹĽ nynĂ­ uzavĂ­rĂĄme vrchol~$v$ s~minimĂĄlnĂ­m $h(v)$ mezi otevřenĂ˝mi. Během jeho +relaxace nemĹŻĹžeme Şådnou hodnotu snĂ­Ĺžit pod~$h(v)$, jelikoĹž v~grafu s~nezĂĄpornĂ˝mi +hranami je $h(v) + \ell(v,w) \ge h(v)$. Hodnota zbĂ˝vajĂ­cĂ­ch otevřenĂ˝ch vrcholĹŻ +tedy neklesne pod hodnotu tohoto nově uzavřenĂŠho. Hodnoty dříve uzavřenĂ˝ch vrcholĹŻ +se nemohou nijak změnit. \qed -Pøímoèará implementace Dijkstrova algoritmu by tedy poka¾dé v~èase $\O(n)$ -vybrala otevøený vrchol s~nejmen¹ím ohodnocením, v~èase $\O(n)$ ho relaxovala -a toto by se opakovalo nejvý¹e $n$-krát. Algoritmus by tudí¾ dobìhl v~èase $\O(n^2)$, -co¾ je pro husté grafy zajisté optimální. Zkusíme nyní zrychlit výpoèet -na~øídkých grafech. - -V¹echny relaxace trvají dohromady $\O(\sum_v \deg(v)) = \O(m)$, tak¾e úzkým hrdlem je -vybírání minima. Pou¾ijeme pro nìj vhodnou datovou strukturu, v~ní¾ budeme udr¾ovat -mno¾inu v¹ech otevøených vrcholù spolu s~jejich ohodnoceními. Od~datové struktury -potøebujeme, aby umìla operace \ (vlo¾ení vrcholu), \ (nalezení -a smazání minima) a \ (sní¾ení hodnoty vrcholu). První dvì operace pøitom -voláme nejvý¹e $n$-krát a operaci \ nejvý¹e $m$-krát. Celý algoritmus -tedy dobìhne v~èase +PřímočarĂĄ implementace Dijkstrova algoritmu by tedy pokaĹždĂŠ v~čase $\O(n)$ +vybrala otevřenĂ˝ vrchol s~nejmenĹĄĂ­m ohodnocenĂ­m, v~čase $\O(n)$ ho relaxovala +a toto by se opakovalo nejvýťe $n$-krĂĄt. Algoritmus by tudĂ­Ĺž doběhl v~čase $\O(n^2)$, +coĹž je pro hustĂŠ grafy zajistĂŠ optimĂĄlnĂ­. ZkusĂ­me nynĂ­ zrychlit vĂ˝počet +na~řídkĂ˝ch grafech. + +VĹĄechny relaxace trvajĂ­ dohromady $\O(\sum_v \deg(v)) = \O(m)$, takĹže ĂşzkĂ˝m hrdlem je +vybĂ­rĂĄnĂ­ minima. PouĹžijeme pro něj vhodnou datovou strukturu, v~nĂ­Ĺž budeme udrĹžovat +mnoĹžinu vĹĄech otevřenĂ˝ch vrcholĹŻ spolu s~jejich ohodnocenĂ­mi. Od~datovĂŠ struktury +potřebujeme, aby uměla operace \ (vloĹženĂ­ vrcholu), \ (nalezenĂ­ +a smazĂĄnĂ­ minima) a \ (snĂ­ĹženĂ­ hodnoty vrcholu). PrvnĂ­ dvě operace přitom +volĂĄme nejvýťe $n$-krĂĄt a operaci \ nejvýťe $m$-krĂĄt. CelĂ˝ algoritmus +tedy doběhne v~čase $$\O(nT_I(n) + nT_E(n) + mT_D(n)),$$ -kde $T_I(n)$, $T_E(n)$ a $T_D(n)$ jsou èasové slo¾itosti jednotlivých operací -na~struktuøe o~nejvý¹e~$n$ prvcích (staèí amortizovanì). +kde $T_I(n)$, $T_E(n)$ a $T_D(n)$ jsou časovĂŠ sloĹžitosti jednotlivĂ˝ch operacĂ­ +na~struktuře o~nejvýťe~$n$ prvcĂ­ch (stačí amortizovaně). -\>Jaké mo¾nosti máme pro volbu struktury? +\>JakĂŠ moĹžnosti mĂĄme pro volbu struktury? \itemize\ibull -\:{\I pole} -- \ a \ stojí konstantu, \ trvá $\O(n)$, +\:{\I pole} -- \ a \ stojĂ­ konstantu, \ trvĂĄ $\O(n)$, celkem tedy $\O(n^2)$. -\:{\I (binární) halda} -- v¹echny tøi operace umíme provést v~èase $\O(\log n)$, tak¾e celkem - $\O(m\log n)$. To je pro husté grafy hor¹í, pro øídké lep¹í. -\:{\I $k$-regulární halda} -- pokud haldu upravíme tak, ¾e ka¾dý prvek bude mít a¾ $k$ synù, - hloubka haldy klesne na~$\O(\log_k n)$. Operace \uv{vybublávající} prvky smìrem nahoru, - co¾ je \ a \, se zrychlí na~$\O(\log_k n)$. Ov¹em \ potøebuje - zkoumat v¹echny syny ka¾dého nav¹tíveného prvku, tak¾e se zpomalí na $\O(k\log_k n)$. - - Celková slo¾itost tedy vyjde $\O(nk\log_k n + m\log_k n)$. Oba èleny se vyrovnají - pro $k=m/n$, èím¾ získáme $\O(m\log_{m/n} n)$. Èlen $\log_{m/n} n$ je pøitom $\O(1)$, - kdykoliv je $m\ge n^{1+\varepsilon}$ pro nìjaké~$\varepsilon>0$, tak¾e pro dostateènì - husté grafy jsme získali lineární algoritmus. - - (V¹imnìte si, ¾e pro $m\approx n^2$ algoritmus zvolí $k\approx n$, tak¾e halda degeneruje - na jediné patro, tedy na pole, které se opravdu ukázalo být optimální volbou pro husté grafy.) -\:{\I Fibonacciho halda} \cite{ft:fibonacci} -- \ a \ stojí $\O(1)$, \ má slo¾itost - $\O(\log n)$ [v¹e amortizovanì]. Dijkstrùv algoritmus proto dobìhne v~èase $\O(m + n\log n)$. - To je lineární pro grafy s~hustotou $\Omega(\log n)$. Té¾e slo¾itosti operací dosahují - i jiné, ménì známé haldy \cite{haeupler:rankph,elmasry:violheap}, které mohou být v~praxi - výraznì rychlej¹í. -\:{\I Monotónní haldy} -- mù¾eme pou¾ít nìjakou jinou haldu, která vyu¾ívá toho, - ¾e posloupnost odebíraných prvkù je neklesající. Pro celá èísla na~\hbox{RAMu} to mù¾e - být napøíklad Thorupova halda \cite{thorup:queue} se slo¾itostí $\O(\log\log n)$ u~operace \ - a $\O(1)$ u~ostatních operací. Dijkstra tedy bì¾í v~$\O(m + n\log\log n)$. -\:{\I Datové struktury pro omezené universum} -- prozkoumáme vzápìtí. +\:{\I (binĂĄrnĂ­) halda} -- vĹĄechny tři operace umĂ­me provĂŠst v~čase $\O(\log n)$, takĹže celkem + $\O(m\log n)$. To je pro hustĂŠ grafy horĹĄĂ­, pro řídkĂŠ lepĹĄĂ­. +\:{\I $k$-regulĂĄrnĂ­ halda} -- pokud haldu upravĂ­me tak, Ĺže kaĹždĂ˝ prvek bude mĂ­t aĹž $k$ synĹŻ, + hloubka haldy klesne na~$\O(\log_k n)$. Operace \uv{vybublĂĄvajĂ­cĂ­} prvky směrem nahoru, + coĹž je \ a \, se zrychlĂ­ na~$\O(\log_k n)$. OvĹĄem \ potřebuje + zkoumat vĹĄechny syny kaĹždĂŠho navĹĄtĂ­venĂŠho prvku, takĹže se zpomalĂ­ na $\O(k\log_k n)$. + + CelkovĂĄ sloĹžitost tedy vyjde $\O(nk\log_k n + m\log_k n)$. Oba členy se vyrovnajĂ­ + pro $k=m/n$, čímĹž zĂ­skĂĄme $\O(m\log_{m/n} n)$. Člen $\log_{m/n} n$ je přitom $\O(1)$, + kdykoliv je $m\ge n^{1+\varepsilon}$ pro nějakĂŠ~$\varepsilon>0$, takĹže pro dostatečně + hustĂŠ grafy jsme zĂ­skali lineĂĄrnĂ­ algoritmus. + + (VĹĄimněte si, Ĺže pro $m\approx n^2$ algoritmus zvolĂ­ $k\approx n$, takĹže halda degeneruje + na jedinĂŠ patro, tedy na pole, kterĂŠ se opravdu ukĂĄzalo bĂ˝t optimĂĄlnĂ­ volbou pro hustĂŠ grafy.) +\:{\I Fibonacciho halda} \cite{ft:fibonacci} -- \ a \ stojĂ­ $\O(1)$, \ mĂĄ sloĹžitost + $\O(\log n)$ [vĹĄe amortizovaně]. DijkstrĹŻv algoritmus proto doběhne v~čase $\O(m + n\log n)$. + To je lineĂĄrnĂ­ pro grafy s~hustotou $\Omega(\log n)$. TĂŠĹže sloĹžitosti operacĂ­ dosahujĂ­ + i jinĂŠ, mĂŠně znĂĄmĂŠ haldy \cite{haeupler:rankph,elmasry:violheap}, kterĂŠ mohou bĂ˝t v~praxi + vĂ˝razně rychlejĹĄĂ­. +\:{\I MonotĂłnnĂ­ haldy} -- mĹŻĹžeme pouŞít nějakou jinou haldu, kterĂĄ vyuŞívĂĄ toho, + Ĺže posloupnost odebĂ­ranĂ˝ch prvkĹŻ je neklesajĂ­cĂ­. Pro celĂĄ čísla na~\hbox{RAMu} to mĹŻĹže + bĂ˝t například Thorupova halda \cite{thorup:queue} se sloĹžitostĂ­ $\O(\log\log n)$ u~operace \ + a $\O(1)$ u~ostatnĂ­ch operacĂ­. Dijkstra tedy běží v~$\O(m + n\log\log n)$. +\:{\I DatovĂŠ struktury pro omezenĂŠ universum} -- prozkoumĂĄme vzĂĄpětĂ­. \endlist -\s{Cvièení:} +\s{CvičenĂ­:} \itemize\ibull -\:Najdìte pøíklad grafu se zápornými hranami (ale bez záporných cyklù), - na~kterém Dijkstrùv algoritmus sel¾e. -\:Rozmyslete si, ¾e pokud nevyu¾ijeme nìjaké speciální vlastnosti èísel (celoèíselnost, - omezený rozsah), je mez $\O(m+n\log n)$ nejlep¹í mo¾ná, proto¾e Dijkstrovým algoritmem - mù¾eme tøídit $n$-tici èísel. Thorup dokonce dokázal \cite{thorup:equiv}, ¾e z~ka¾dého tøídícího algoritmu - se slo¾itostí $\O(nT(n))$ mù¾eme odvodit haldu se slo¾itostí mazání $\O(T(n))$. -\:Jsou-li délky hran celoèíselné, mù¾eme se na Dijkstrùv algoritmus dívat i takto: - Pøedstavme si, ¾e ka¾dou hranu nahradíme cestou tvoøenou pøíslu¹ným poètem hran jednotkové délky - a na vzniklý neohodnocený graf spustíme prohledávání do~¹íøky. To samozøejmì vydá - správný výsledek, ale pomìrnì pomalu, proto¾e bude vìt¹inu èasu trávit posouváním - vlny \uv{uvnitø} pùvodních hran. Mù¾eme si tedy pro ka¾dou pùvodní hranu naøídit - \uv{budík}, který nám øekne, za~kolik posunutí vlny dospìjeme na~její konec. - Doka¾te, ¾e tento algoritmus je ekvivalentní s~Dijkstrovým. +\:Najděte příklad grafu se zĂĄpornĂ˝mi hranami (ale bez zĂĄpornĂ˝ch cyklĹŻ), + na~kterĂŠm DijkstrĹŻv algoritmus selĹže. +\:Rozmyslete si, Ĺže pokud nevyuĹžijeme nějakĂŠ speciĂĄlnĂ­ vlastnosti čísel (celočíselnost, + omezenĂ˝ rozsah), je mez $\O(m+n\log n)$ nejlepĹĄĂ­ moĹžnĂĄ, protoĹže DijkstrovĂ˝m algoritmem + mĹŻĹžeme třídit $n$-tici čísel. Thorup dokonce dokĂĄzal \cite{thorup:equiv}, Ĺže z~kaĹždĂŠho třídĂ­cĂ­ho algoritmu + se sloĹžitostĂ­ $\O(nT(n))$ mĹŻĹžeme odvodit haldu se sloĹžitostĂ­ mazĂĄnĂ­ $\O(T(n))$. +\:Jsou-li dĂŠlky hran celočíselnĂŠ, mĹŻĹžeme se na DijkstrĹŻv algoritmus dĂ­vat i takto: + Představme si, Ĺže kaĹždou hranu nahradĂ­me cestou tvořenou přísluĹĄnĂ˝m počtem hran jednotkovĂŠ dĂŠlky + a na vzniklĂ˝ neohodnocenĂ˝ graf spustĂ­me prohledĂĄvĂĄnĂ­ do~šířky. To samozřejmě vydĂĄ + sprĂĄvnĂ˝ vĂ˝sledek, ale poměrně pomalu, protoĹže bude větĹĄinu času trĂĄvit posouvĂĄnĂ­m + vlny \uv{uvnitř} pĹŻvodnĂ­ch hran. MĹŻĹžeme si tedy pro kaĹždou pĹŻvodnĂ­ hranu nařídit + \uv{budĂ­k}, kterĂ˝ nĂĄm řekne, za~kolik posunutĂ­ vlny dospějeme na~jejĂ­ konec. + DokaĹžte, Ĺže tento algoritmus je ekvivalentnĂ­ s~DijkstrovĂ˝m. \endlist -\h{Celoèíselné délky} - -Uva¾ujme nyní grafy, v~nich¾ jsou v¹echny délky hran nezáporná celá èísla omezená -nìjakou konstantou~$L$. V¹echny vzdálenosti jsou tedy omezeny èíslem~$nL$, tak¾e -nám staèí datová struktura schopná uchovávat takto omezená celá èísla. - -Pou¾ijeme jednoduchou pøihrádkovou strukturu: pole indexované hodnotami od~0 do~$nL$, -jeho $i$-tý prvek bude obsahovat seznam vrcholù, jejich¾ ohodnocení je rovno~$i$. -Operace \ a \ zvládneme v~konstantním èase, budeme-li si u~ka¾dého -prvku pamatovat jeho polohu v~seznamu. Operace \ potøebuje najít první -neprázdnou pøihrádku, ale jeliko¾ víme, ¾e posloupnost odebíraných minim je monotónní, -staèí hledat od místa, kde se hledání zastavilo minule. V¹echna hledání pøihrádek -tedy zaberou dohromady $\O(nL)$ a celý Dijkstrùv algoritmus bude trvat $\O(nL + m)$. - -Prostorová slo¾itost $\O(nL+m)$ je nevalná, ale mù¾eme ji jednoduchým trikem -sní¾it: V¹imneme si, ¾e v¹echna koneèná ohodnocení vrcholù nemohou být vìt¹í -ne¾ aktuální minimum zvìt¹ené o~$L$. Jinými slovy v¹echny neprázdné pøihrádky -se nacházejí v~úseku pole dlouhém~$L+1$, tak¾e staèí indexovat modulo~$L+1$. -Pouze si musíme dávat pozor, abychom správnì poznali, kdy se struktura -vyprázdnila, co¾ zjistíme napøíklad pomocí poèítadla otevøených vrcholù. Èas si -asymptoticky nezhor¹íme, prostor klesne na~$\O(L+m)$. - -Podobný trik mù¾eme pou¾ít i pro libovolnou jinou datovou strukturu: rozsah èísel -rozdìlíme na~\uv{okna} velikosti~$L$ (v~$i$-tém oknì jsou èísla $iL,iL+1,\ldots,(i+1)L-1$). -V~libovolné chvíli mohou tedy být neprázdná nejvý¹e dvì okna. Staèí nám proto -poøídit si dvì struktury pro ukládání èísel v~rozsahu $0,\ldots,L-1$ -- jedna -z~nich bude reprezentovat aktuální okno (to, v~nìm¾ le¾elo minulé minimum), -druhá okno bezprostøednì následující. Minimum ma¾eme z~první struktury; pokud -u¾ je prázdná, obì struktury prohodíme. Operace \ podle hodnoty urèí, -do~které struktury se má vkládat. S~operací \ je to slo¾itìj¹í -- -hodnota z~vy¹¹í struktury mù¾e pøeskoèit do té ni¾¹í, ale v~takovém pøípadì -ji ve~vy¹¹í struktuøe vyma¾eme (to je \ na $-\infty$ následovaný -\em) a do~té ni¾¹í vlo¾íme. To se ka¾dému prvku mù¾e pøihodit nejvý¹e -jednou, tak¾e stále platí, ¾e se ka¾dý prvek úèastní $\O(1)$ vlo¾ení a $\O(1)$ -extrakcí minima. - -Ukázali jsme tedy, ¾e pro na¹e potøeby postaèuje struktura schopná uchovávání -èísel men¹ích nebo rovných~$L$. - -Nabízí se pou¾ít van Emde-Boasùv strom z~kapitoly o~výpoèetních modelech. -Ten dosahuje slo¾itosti $\O(\log\log L)$ pro operace \ a \, -operaci \ musíme pøekládat na \ a \. Celková -slo¾itost Dijkstrova algoritmu vyjde $\O(L+m\log\log L)$, pøièem¾ èas~$L$ -spotøebujeme na inicializaci struktury (té se lze za jistých podmínek vyhnout, -viz zmínìná kapitola). - -Vra»me se ale je¹tì k~vyu¾ití pøihrádek\dots - -\h{Víceúrovòové pøihrádky} - -Podobnì jako u~tøídìní èísel, i~zde se vyplácí stavìt pøihrádkové struktury -víceúrovòovì (pùvodnì popsáno Goldbergem a Silversteinem \cite{goldberg:mlb}). -Jednotlivé hodnoty budeme zapisovat v~soustavì o~základu~$B$, -který zvolíme jako nìjakou mocninu dvojky, abychom mohli s~èíslicemi tohoto -zápisu snadno zacházet pomocí bitových operací. Ka¾dé èíslo tedy zabere nejvý¹e -$d=1+\lfloor\log_B L\rfloor$ èíslic; pokud bude krat¹í, doplníme ho zleva nulami. - -Nejvy¹¹í patro struktury bude tvoøeno polem $B$~pøihrádek, v~$i$-té z~nich -budou ulo¾ena ta èísla, jejich¾ èíslice nejvy¹¹ího øádu je rovna~$i$. Za~{\I aktivní} -prohlásíme tu pøihrádku, která obsahuje aktuální minimum. Pøihrádky s~men¹ími -indexy jsou prázdné a zùstanou takové a¾ do~konce výpoètu, proto¾e halda -je monotónní. Pokud v~pøihrádce obsahující minimum bude více prvkù, budeme -ji rozkládat podle druhého nejvy¹¹ího øádu na dal¹ích~$B$ pøihrádek atd. -Celkem tak vznikne a¾~$d$ úrovní. - -\>Struktura bude obsahovat následující data: +\h{CeločíselnĂŠ dĂŠlky} + +UvaĹžujme nynĂ­ grafy, v~nichĹž jsou vĹĄechny dĂŠlky hran nezĂĄpornĂĄ celĂĄ čísla omezenĂĄ +nějakou konstantou~$L$. VĹĄechny vzdĂĄlenosti jsou tedy omezeny číslem~$nL$, takĹže +nĂĄm stačí datovĂĄ struktura schopnĂĄ uchovĂĄvat takto omezenĂĄ celĂĄ čísla. + +PouĹžijeme jednoduchou přihrĂĄdkovou strukturu: pole indexovanĂŠ hodnotami od~0 do~$nL$, +jeho $i$-tĂ˝ prvek bude obsahovat seznam vrcholĹŻ, jejichĹž ohodnocenĂ­ je rovno~$i$. +Operace \ a \ zvlĂĄdneme v~konstantnĂ­m čase, budeme-li si u~kaĹždĂŠho +prvku pamatovat jeho polohu v~seznamu. Operace \ potřebuje najĂ­t prvnĂ­ +neprĂĄzdnou přihrĂĄdku, ale jelikoĹž vĂ­me, Ĺže posloupnost odebĂ­ranĂ˝ch minim je monotĂłnnĂ­, +stačí hledat od mĂ­sta, kde se hledĂĄnĂ­ zastavilo minule. VĹĄechna hledĂĄnĂ­ přihrĂĄdek +tedy zaberou dohromady $\O(nL)$ a celĂ˝ DijkstrĹŻv algoritmus bude trvat $\O(nL + m)$. + +ProstorovĂĄ sloĹžitost $\O(nL+m)$ je nevalnĂĄ, ale mĹŻĹžeme ji jednoduchĂ˝m trikem +snĂ­Ĺžit: VĹĄimneme si, Ĺže vĹĄechna konečnĂĄ ohodnocenĂ­ vrcholĹŻ nemohou bĂ˝t větĹĄĂ­ +neĹž aktuĂĄlnĂ­ minimum zvětĹĄenĂŠ o~$L$. JinĂ˝mi slovy vĹĄechny neprĂĄzdnĂŠ přihrĂĄdky +se nachĂĄzejĂ­ v~Ăşseku pole dlouhĂŠm~$L+1$, takĹže stačí indexovat modulo~$L+1$. +Pouze si musĂ­me dĂĄvat pozor, abychom sprĂĄvně poznali, kdy se struktura +vyprĂĄzdnila, coĹž zjistĂ­me například pomocĂ­ počítadla otevřenĂ˝ch vrcholĹŻ. Čas si +asymptoticky nezhorĹĄĂ­me, prostor klesne na~$\O(L+m)$. + +PodobnĂ˝ trik mĹŻĹžeme pouŞít i pro libovolnou jinou datovou strukturu: rozsah čísel +rozdělĂ­me na~\uv{okna} velikosti~$L$ (v~$i$-tĂŠm okně jsou čísla $iL,iL+1,\ldots,(i+1)L-1$). +V~libovolnĂŠ chvĂ­li mohou tedy bĂ˝t neprĂĄzdnĂĄ nejvýťe dvě okna. Stačí nĂĄm proto +pořídit si dvě struktury pro uklĂĄdĂĄnĂ­ čísel v~rozsahu $0,\ldots,L-1$ -- jedna +z~nich bude reprezentovat aktuĂĄlnĂ­ okno (to, v~němĹž leĹželo minulĂŠ minimum), +druhĂĄ okno bezprostředně nĂĄsledujĂ­cĂ­. Minimum maĹžeme z~prvnĂ­ struktury; pokud +uĹž je prĂĄzdnĂĄ, obě struktury prohodĂ­me. Operace \ podle hodnoty určí, +do~kterĂŠ struktury se mĂĄ vklĂĄdat. S~operacĂ­ \ je to sloĹžitějĹĄĂ­ -- +hodnota z~vyĹĄĹĄĂ­ struktury mĹŻĹže přeskočit do tĂŠ niŞťí, ale v~takovĂŠm případě +ji ve~vyĹĄĹĄĂ­ struktuře vymaĹžeme (to je \ na $-\infty$ nĂĄsledovanĂ˝ +\em) a do~tĂŠ niŞťí vloŞíme. To se kaĹždĂŠmu prvku mĹŻĹže přihodit nejvýťe +jednou, takĹže stĂĄle platĂ­, Ĺže se kaĹždĂ˝ prvek účastnĂ­ $\O(1)$ vloĹženĂ­ a $\O(1)$ +extrakcĂ­ minima. + +UkĂĄzali jsme tedy, Ĺže pro naĹĄe potřeby postačuje struktura schopnĂĄ uchovĂĄvĂĄnĂ­ +čísel menĹĄĂ­ch nebo rovnĂ˝ch~$L$. + +NabĂ­zĂ­ se pouŞít van Emde-BoasĹŻv strom z~kapitoly o~vĂ˝početnĂ­ch modelech. +Ten dosahuje sloĹžitosti $\O(\log\log L)$ pro operace \ a \, +operaci \ musĂ­me překlĂĄdat na \ a \. CelkovĂĄ +sloĹžitost Dijkstrova algoritmu vyjde $\O(L+m\log\log L)$, přičemĹž čas~$L$ +spotřebujeme na inicializaci struktury (tĂŠ se lze za jistĂ˝ch podmĂ­nek vyhnout, +viz zmĂ­něnĂĄ kapitola). + +VraĹĽme se ale jeĹĄtě k~vyuĹžitĂ­ přihrĂĄdek\dots + +\h{VĂ­ceĂşrovňovĂŠ přihrĂĄdky} + +Podobně jako u~tříděnĂ­ čísel, i~zde se vyplĂĄcĂ­ stavět přihrĂĄdkovĂŠ struktury +vĂ­ceĂşrovňově (pĹŻvodně popsĂĄno Goldbergem a Silversteinem \cite{goldberg:mlb}). +JednotlivĂŠ hodnoty budeme zapisovat v~soustavě o~zĂĄkladu~$B$, +kterĂ˝ zvolĂ­me jako nějakou mocninu dvojky, abychom mohli s~číslicemi tohoto +zĂĄpisu snadno zachĂĄzet pomocĂ­ bitovĂ˝ch operacĂ­. KaĹždĂŠ číslo tedy zabere nejvýťe +$d=1+\lfloor\log_B L\rfloor$ číslic; pokud bude kratĹĄĂ­, doplnĂ­me ho zleva nulami. + +NejvyĹĄĹĄĂ­ patro struktury bude tvořeno polem $B$~přihrĂĄdek, v~$i$-tĂŠ z~nich +budou uloĹžena ta čísla, jejichĹž číslice nejvyĹĄĹĄĂ­ho řádu je rovna~$i$. Za~{\I aktivnĂ­} +prohlĂĄsĂ­me tu přihrĂĄdku, kterĂĄ obsahuje aktuĂĄlnĂ­ minimum. PřihrĂĄdky s~menĹĄĂ­mi +indexy jsou prĂĄzdnĂŠ a zĹŻstanou takovĂŠ aĹž do~konce vĂ˝počtu, protoĹže halda +je monotĂłnnĂ­. Pokud v~přihrĂĄdce obsahujĂ­cĂ­ minimum bude vĂ­ce prvkĹŻ, budeme +ji rozklĂĄdat podle druhĂŠho nejvyĹĄĹĄĂ­ho řádu na dalĹĄĂ­ch~$B$ přihrĂĄdek atd. +Celkem tak vznikne aĹž~$d$ ĂşrovnĂ­. + +\>Struktura bude obsahovat nĂĄsledujĂ­cĂ­ data: \itemize\ibull \:Parametry $L$, $B$ a~$d$. -\:Pole úrovní (nejvy¹¹í má èíslo~$d-1$, nejni¾¹í~0), ka¾dá úroveò je buïto prázdná - (a pak jsou prázdné i~v¹echny ni¾¹í), nebo obsahuje pole~$U_i$ o~$B$ pøihrádkách - a v~ka¾dé z~nich seznam prvkù. Pole úrovní pou¾íváme jako zásobník, udr¾ujeme - si èíslo nejni¾¹í neprázdné úrovnì. -\:Hodnotu~$\mu$ pøedchozího odebraného minima. +\:Pole ĂşrovnĂ­ (nejvyĹĄĹĄĂ­ mĂĄ číslo~$d-1$, nejniŞťí~0), kaĹždĂĄ Ăşroveň je buďto prĂĄzdnĂĄ + (a pak jsou prĂĄzdnĂŠ i~vĹĄechny niŞťí), nebo obsahuje pole~$U_i$ o~$B$ přihrĂĄdkĂĄch + a v~kaĹždĂŠ z~nich seznam prvkĹŻ. Pole ĂşrovnĂ­ pouŞívĂĄme jako zĂĄsobnĂ­k, udrĹžujeme + si číslo nejniŞťí neprĂĄzdnĂŠ Ăşrovně. +\:Hodnotu~$\mu$ předchozĂ­ho odebranĂŠho minima. \endlist -Operace \ vlo¾í hodnotu do~nejhlub¹í mo¾né pøihrádky. Podívá se tedy -na~nejvy¹¹í úroveò: pokud hodnota patøí do pøihrádky, která není aktivní, vlo¾í -ji pøímo. Jinak pøejde o~úroveò ní¾e a zopakuje stejný postup. To v¹e lze provést -v~konstantním èase: staèí se podívat, jaký je nejvy¹¹í jednièkový bit ve~{\sc xor}u -nové hodnoty s~èíslem~$\mu$ (opìt viz kapitola o~výpoèetních modelech), a tím zjistit -èíslo úrovnì, kam hodnota patøí. +Operace \ vloŞí hodnotu do~nejhlubĹĄĂ­ moĹžnĂŠ přihrĂĄdky. PodĂ­vĂĄ se tedy +na~nejvyĹĄĹĄĂ­ Ăşroveň: pokud hodnota patří do přihrĂĄdky, kterĂĄ nenĂ­ aktivnĂ­, vloŞí +ji přímo. Jinak přejde o~Ăşroveň nĂ­Ĺže a zopakuje stejnĂ˝ postup. To vĹĄe lze provĂŠst +v~konstantnĂ­m čase: stačí se podĂ­vat, jakĂ˝ je nejvyĹĄĹĄĂ­ jedničkovĂ˝ bit ve~{\sc xor}u +novĂŠ hodnoty s~číslem~$\mu$ (opět viz kapitola o~vĂ˝početnĂ­ch modelech), a tĂ­m zjistit +číslo Ăşrovně, kam hodnota patří. -Pokud chceme provést \, odstraníme hodnotu z~pøihrádky, ve~které se -právì nachází (polohu si mù¾eme u~ka¾dé hodnoty pamatovat zvlá¹»), a znovu ji -vlo¾íme. +Pokud chceme provĂŠst \, odstranĂ­me hodnotu z~přihrĂĄdky, ve~kterĂŠ se +prĂĄvě nachĂĄzĂ­ (polohu si mĹŻĹžeme u~kaĹždĂŠ hodnoty pamatovat zvlĂĄĹĄĹĽ), a znovu ji +vloŞíme. -Vìt¹inu práce samozøejmì pøenecháme funkci \. Ta zaène prohledávat -nejni¾¹í obsazenou úroveò od~aktivní pøihrádky dál (to, která pøihrádka je na -které úrovni aktivní, poznáme z~èíslic hodnoty~$\mu$). Pokud pøihrádky na~této -úrovni dojdou, prázdnou úroveò zru¹íme a pokraèujeme o~patro vý¹e. +VětĹĄinu prĂĄce samozřejmě přenechĂĄme funkci \. Ta začne prohledĂĄvat +nejniŞťí obsazenou Ăşroveň od~aktivnĂ­ přihrĂĄdky dĂĄl (to, kterĂĄ přihrĂĄdka je na +kterĂŠ Ăşrovni aktivnĂ­, poznĂĄme z~číslic hodnoty~$\mu$). Pokud přihrĂĄdky na~tĂŠto +Ăşrovni dojdou, prĂĄzdnou Ăşroveň zruĹĄĂ­me a pokračujeme o~patro výťe. -Jakmile najdeme neprázdnou pøihrádku, nalezneme v~ní minimum a to se stane novým~$\mu$. -Pokud v~pøihrádce nebyly ¾ádné dal¹í prvky, skonèíme. V~opaèném pøípadì zbývající -prvky rozprostøeme do~pøihrádek na~bezprostøednì ni¾¹í úrovni, kterou tím zalo¾íme. +Jakmile najdeme neprĂĄzdnou přihrĂĄdku, nalezneme v~nĂ­ minimum a to se stane novĂ˝m~$\mu$. +Pokud v~přihrĂĄdce nebyly ŞådnĂŠ dalĹĄĂ­ prvky, skončíme. V~opačnĂŠm případě zbĂ˝vajĂ­cĂ­ +prvky rozprostřeme do~přihrĂĄdek na~bezprostředně niŞťí Ăşrovni, kterou tĂ­m zaloŞíme. -Èas strávený hledáním minima mù¾eme rozdìlit na~nìkolik èástí: +Čas strĂĄvenĂ˝ hledĂĄnĂ­m minima mĹŻĹžeme rozdělit na~několik částĂ­: \itemize\ibull -\:$\O(B)$ na inicializaci nové úrovnì -- to naúètujeme prvku, který jsme - právì mazali; -\:hledání neprázdných pøihrádek -- prozkoumání ka¾dé prázdné pøihrádky - naúètujeme jejímu vytvoøení, co¾ se rozpustí v~$\O(B)$ na inicializaci - úrovnì; -\:zru¹ení úrovnì -- opìt naúètujeme jejímu vzniku; -\:rozhazování prvkù do pøihrádek -- jeliko¾ prvky v~hierarchii pøihrádek - putují bìhem operací pouze doleva a dolù (jejich hodnoty se nikdy nezvìt¹ují), - klesne ka¾dý prvek nejvý¹e~$d$-krát, tak¾e staèí, kdy¾ na v¹echna rozhazování - pøispìje èasem $\O(d)$. +\:$\O(B)$ na inicializaci novĂŠ Ăşrovně -- to naúčtujeme prvku, kterĂ˝ jsme + prĂĄvě mazali; +\:hledĂĄnĂ­ neprĂĄzdnĂ˝ch přihrĂĄdek -- prozkoumĂĄnĂ­ kaĹždĂŠ prĂĄzdnĂŠ přihrĂĄdky + naúčtujeme jejĂ­mu vytvořenĂ­, coĹž se rozpustĂ­ v~$\O(B)$ na inicializaci + Ăşrovně; +\:zruĹĄenĂ­ Ăşrovně -- opět naúčtujeme jejĂ­mu vzniku; +\:rozhazovĂĄnĂ­ prvkĹŻ do přihrĂĄdek -- jelikoĹž prvky v~hierarchii přihrĂĄdek + putujĂ­ během operacĂ­ pouze doleva a dolĹŻ (jejich hodnoty se nikdy nezvětĹĄujĂ­), + klesne kaĹždĂ˝ prvek nejvýťe~$d$-krĂĄt, takĹže stačí, kdyĹž na vĹĄechna rozhazovĂĄnĂ­ + přispěje časem $\O(d)$. \endlist -\>Staèí tedy, aby ka¾dý prvek pøi \u zaplatil èas $\O(B+d)$ a jak \, -tak \ budou mít konstantní amortizovanou slo¾itost. Dijkstrùv -algoritmus pak pobì¾í v~$\O(m + n(B+d))$. +\>Stačí tedy, aby kaĹždĂ˝ prvek při \u zaplatil čas $\O(B+d)$ a jak \, +tak \ budou mĂ­t konstantnĂ­ amortizovanou sloĹžitost. DijkstrĹŻv +algoritmus pak poběží v~$\O(m + n(B+d))$. -Zbývá nastavit parametry tak, abychom minimalizovali výraz $B+d = B + \log L/\log B$. -Vhodná volba je $B=\log L/\log\log L$. Pøi ní platí +ZbĂ˝vĂĄ nastavit parametry tak, abychom minimalizovali vĂ˝raz $B+d = B + \log L/\log B$. +VhodnĂĄ volba je $B=\log L/\log\log L$. Při nĂ­ platĂ­ $$ {\log L\over\log B} = {\log L \over \log\left(\log L/\log\log L\right) } = {\log L\over \log\log L - \log\log\log L} = \Theta(B). $$ -Tehdy Dijkstra vydá výsledek v~èase $\O(m + n\cdot{\log L\over\log\log L})$. - -\h{HOT Queue -- kombinace pøihrádek s~haldou} - -Cherkassky, Goldberg a Silverstein \cite{cherkassky:hotq} si v¹imli, ¾e ve~víceúrovòových pøihrádkových strukturách -platíme pøíli¹ mnoho za~úrovnì, ve~kterých se za~dobu jejich existence objeví jen malé -mno¾ství prvkù. Navrhli tedy ukládat prvky z~\uv{malých} úrovní do~spoleèné haldy. -Výsledné struktuøe se øíká HOT (Heap-on-Top) Queue. My si pøedvedeme její upravenou -variantu (v~té pùvodní se skrývá nìkolik chyb). - -Poøídíme si haldu, øeknìme Fibonacciho, a~navíc ke~ka¾dé úrovni poèítadlo udávající, -kolik prvkù z~této úrovnì jsme ulo¾ili do~haldy. Dokud toto poèítadlo nepøeroste nìjaký -parametr~$H$, pøihrádky nebudeme zakládat a prvky poputují do~haldy. Èas $\O(B)$ na -zalo¾ení úrovnì a její procházení proto mù¾eme rozpoèítat mezi~$H$ prvkù, které se musely -na~dané úrovni objevit, ne¾ byla rozpøihrádkována. (Pov¹imnìte si, ¾e poèítadlo nikdy -nesni¾ujeme, pouze ho vynulujeme, kdy¾ je úroveò zru¹ena. Proto vùbec nemusí odpovídat -skuteènému poètu prvkù z~pøíslu¹né úrovnì, které jsou právì ulo¾eny v~haldì. To ov¹em -vùbec nevadí -- poèítadlo pouze hlídá, aby se úroveò nevytvoøila pøíli¹ brzy, tedy abychom -mìli dost prvkù k~rozúètování èasu.) - -Promìnnou~$\mu$ necháme ukazovat na~místo, kde jsme se pøi hledání minima v~pøihrádkách -zastavili. Souèasné globální minimum struktury mù¾e být ni¾¹í, nachází-li se minimum -zrovna v~haldì. Stále je v¹ak zaruèeno, ¾e pøed~$\mu$ se nenachází ¾ádná -neprázdná pøihrádka. +Tehdy Dijkstra vydĂĄ vĂ˝sledek v~čase $\O(m + n\cdot{\log L\over\log\log L})$. + +\h{HOT Queue -- kombinace přihrĂĄdek s~haldou} + +Cherkassky, Goldberg a Silverstein \cite{cherkassky:hotq} si vĹĄimli, Ĺže ve~vĂ­ceĂşrovňovĂ˝ch přihrĂĄdkovĂ˝ch strukturĂĄch +platĂ­me příliĹĄ mnoho za~Ăşrovně, ve~kterĂ˝ch se za~dobu jejich existence objevĂ­ jen malĂŠ +mnoĹžstvĂ­ prvkĹŻ. Navrhli tedy uklĂĄdat prvky z~\uv{malĂ˝ch} ĂşrovnĂ­ do~společnĂŠ haldy. +VĂ˝slednĂŠ struktuře se říkĂĄ HOT (Heap-on-Top) Queue. My si předvedeme jejĂ­ upravenou +variantu (v~tĂŠ pĹŻvodnĂ­ se skrĂ˝vĂĄ několik chyb). + +PořídĂ­me si haldu, řekněme Fibonacciho, a~navĂ­c ke~kaĹždĂŠ Ăşrovni počítadlo udĂĄvajĂ­cĂ­, +kolik prvkĹŻ z~tĂŠto Ăşrovně jsme uloĹžili do~haldy. Dokud toto počítadlo nepřeroste nějakĂ˝ +parametr~$H$, přihrĂĄdky nebudeme zaklĂĄdat a prvky poputujĂ­ do~haldy. Čas $\O(B)$ na +zaloĹženĂ­ Ăşrovně a jejĂ­ prochĂĄzenĂ­ proto mĹŻĹžeme rozpočítat mezi~$H$ prvkĹŻ, kterĂŠ se musely +na~danĂŠ Ăşrovni objevit, neĹž byla rozpřihrĂĄdkovĂĄna. (PovĹĄimněte si, Ĺže počítadlo nikdy +nesniĹžujeme, pouze ho vynulujeme, kdyĹž je Ăşroveň zruĹĄena. Proto vĹŻbec nemusĂ­ odpovĂ­dat +skutečnĂŠmu počtu prvkĹŻ z~přísluĹĄnĂŠ Ăşrovně, kterĂŠ jsou prĂĄvě uloĹženy v~haldě. To ovĹĄem +vĹŻbec nevadĂ­ -- počítadlo pouze hlĂ­dĂĄ, aby se Ăşroveň nevytvořila příliĹĄ brzy, tedy abychom +měli dost prvkĹŻ k~rozúčtovĂĄnĂ­ času.) + +Proměnnou~$\mu$ nechĂĄme ukazovat na~mĂ­sto, kde jsme se při hledĂĄnĂ­ minima v~přihrĂĄdkĂĄch +zastavili. SoučasnĂŠ globĂĄlnĂ­ minimum struktury mĹŻĹže bĂ˝t niŞťí, nachĂĄzĂ­-li se minimum +zrovna v~haldě. StĂĄle je vĹĄak zaručeno, Ĺže před~$\mu$ se nenachĂĄzĂ­ ŞådnĂĄ +neprĂĄzdnĂĄ přihrĂĄdka. Operace budou fungovat takto: \>\: \algo -\:Spoèítáme, do~které úrovnì~$i$ má prvek padnout (bitovými operacemi). -\:Pokud je poèítadlo této úrovnì men¹í ne¾~$H$, zvý¹íme ho, vlo¾íme prvek do~haldy a skoèíme. -\:Nebyly-li je¹tì pro tuto úroveò zalo¾eny pøihrádky, vyrobíme prázdné. -\:Vlo¾íme prvek do~pøíslu¹né pøihrádky. +\:SpočítĂĄme, do~kterĂŠ Ăşrovně~$i$ mĂĄ prvek padnout (bitovĂ˝mi operacemi). +\:Pokud je počítadlo tĂŠto Ăşrovně menĹĄĂ­ neĹž~$H$, zvýťíme ho, vloŞíme prvek do~haldy a skočíme. +\:Nebyly-li jeĹĄtě pro tuto Ăşroveň zaloĹženy přihrĂĄdky, vyrobĂ­me prĂĄzdnĂŠ. +\:VloŞíme prvek do~přísluĹĄnĂŠ přihrĂĄdky. \endalgo \>\: \algo -\:Pokud se prvek nachází v~haldì (to si u~ka¾dého prvku pamatujeme), provedeme - \ v~haldì a skonèíme. -\:Sma¾eme prvek z~jeho pøihrádky a provedeme \ s~novou hodnotou. +\:Pokud se prvek nachĂĄzĂ­ v~haldě (to si u~kaĹždĂŠho prvku pamatujeme), provedeme + \ v~haldě a skončíme. +\:SmaĹžeme prvek z~jeho přihrĂĄdky a provedeme \ s~novou hodnotou. \endalgo \>\: \algo -\:Dokud je~$\mu$ men¹í ne¾ aktuální minimum haldy, opakujeme: -\::Najdeme pøihrádku odpovídající hodnotì~$\mu$. -\::Je-li tato pøihrádka prázdná, pøejdeme na~dal¹í (upravíme~$\mu$). Jsme-li na konci úrovnì, - zru¹íme ji, vynulujeme její poèítadlo a pokraèujeme o~úroveò vý¹. -\::Není-li prázdná, rozprostøeme ji o~úroveò ní¾ (stejným zpùsobem jako pøi \u, - tak¾e prvních~$H$ prvkù vlo¾íme do~haldy). -\:Sma¾eme minimum z~haldy a vrátíme ho jako výsledek. +\:Dokud je~$\mu$ menĹĄĂ­ neĹž aktuĂĄlnĂ­ minimum haldy, opakujeme: +\::Najdeme přihrĂĄdku odpovĂ­dajĂ­cĂ­ hodnotě~$\mu$. +\::Je-li tato přihrĂĄdka prĂĄzdnĂĄ, přejdeme na~dalĹĄĂ­ (upravĂ­me~$\mu$). Jsme-li na konci Ăşrovně, + zruĹĄĂ­me ji, vynulujeme jejĂ­ počítadlo a pokračujeme o~Ăşroveň výť. +\::NenĂ­-li prĂĄzdnĂĄ, rozprostřeme ji o~Ăşroveň nĂ­Ĺž (stejnĂ˝m zpĹŻsobem jako při \u, + takĹže prvnĂ­ch~$H$ prvkĹŻ vloŞíme do~haldy). +\:SmaĹžeme minimum z~haldy a vrĂĄtĂ­me ho jako vĂ˝sledek. \endalgo -\>Pustíme se do~analýzy slo¾itosti. Jako parametry si zvolíme poèet hladin~$d$ (tak¾e -poèet pøihrádek~$B$ na jedné úrovni je roven $L^{1/d}$) a \uv{haldovou konstantu}~$H$. +\>PustĂ­me se do~analĂ˝zy sloĹžitosti. Jako parametry si zvolĂ­me počet hladin~$d$ (takĹže +počet přihrĂĄdek~$B$ na jednĂŠ Ăşrovni je roven $L^{1/d}$) a \uv{haldovou konstantu}~$H$. -Nejprve si v¹imneme, ¾e ne¾ poèítadlo nìjaké úrovnì vynulujeme, jsou bezpeènì -z~haldy pryè v¹echny prvky patøící do~této úrovnì. Celkem se tedy v~haldì -vyskytuje nejvý¹e $\O(dH)$ prvkù. \ v~haldì proto trvá $\O(\log(dH))$, -ostatní haldové operace $\O(1)$. +Nejprve si vĹĄimneme, Ĺže neĹž počítadlo nějakĂŠ Ăşrovně vynulujeme, jsou bezpečně +z~haldy pryč vĹĄechny prvky patřícĂ­ do~tĂŠto Ăşrovně. Celkem se tedy v~haldě +vyskytuje nejvýťe $\O(dH)$ prvkĹŻ. \ v~haldě proto trvĂĄ $\O(\log(dH))$, +ostatnĂ­ haldovĂŠ operace $\O(1)$. -Nyní rozúètujeme èas operací mezi jednotlivé prvky (opìt si v¹e pøedplatíme -v~\u a ostatní operace pobì¾í v~amortizovanì konstantním èase): +NynĂ­ rozúčtujeme čas operacĂ­ mezi jednotlivĂŠ prvky (opět si vĹĄe předplatĂ­me +v~\u a ostatnĂ­ operace poběží v~amortizovaně konstantnĂ­m čase): \itemize\ibull -\:Ka¾dý prvek mù¾e být nejvý¹e jednou za~dobu svého ¾ivota vlo¾en do~haldy - a nejvý¹e jednou z~ní vyjmut. Na~obojí dohromady pøispìje $\O(\log dH)$. -\:Prvek se úèastní nejvý¹e~$d$ pøehození do~ni¾¹í úrovnì. Pokud byl pøihozen - do~haldy, u¾ tam setrvá, jinak poka¾dé zaplatí $\O(1)$ za~zaøazení do~pøihrádky, +\:KaĹždĂ˝ prvek mĹŻĹže bĂ˝t nejvýťe jednou za~dobu svĂŠho Ĺživota vloĹžen do~haldy + a nejvýťe jednou z~nĂ­ vyjmut. Na~obojĂ­ dohromady přispěje $\O(\log dH)$. +\:Prvek se účastnĂ­ nejvýťe~$d$ přehozenĂ­ do~niŞťí Ăşrovně. Pokud byl přihozen + do~haldy, uĹž tam setrvĂĄ, jinak pokaĹždĂŠ zaplatĂ­ $\O(1)$ za~zařazenĂ­ do~přihrĂĄdky, celkem tedy $\O(d)$ na prvek. -\:Vytvoøení, projití a smazání pøihrádek na~jedné úrovni nastane a¾ tehdy, co bylo - $H$~prvkù patøících do~této úrovnì vlo¾eno do~haldy. Staèí tedy, aby ka¾dý - prvek pøispìl èasem $\O(B/H) = \O(L^{1/d}/H)$. +\:VytvořenĂ­, projitĂ­ a smazĂĄnĂ­ přihrĂĄdek na~jednĂŠ Ăşrovni nastane aĹž tehdy, co bylo + $H$~prvkĹŻ patřícĂ­ch do~tĂŠto Ăşrovně vloĹženo do~haldy. Stačí tedy, aby kaĹždĂ˝ + prvek přispěl časem $\O(B/H) = \O(L^{1/d}/H)$. \endlist -\>Ka¾dý prvek tedy platí $\O(d + \log dH + L^{1/d}/H) = \O(d + \log H + L^{1/d}/H)$. -Pojïme najít nastavení parametrù, které tento výraz minimalizuje. +\>KaĹždĂ˝ prvek tedy platĂ­ $\O(d + \log dH + L^{1/d}/H) = \O(d + \log H + L^{1/d}/H)$. +Pojďme najĂ­t nastavenĂ­ parametrĹŻ, kterĂŠ tento vĂ˝raz minimalizuje. Nejprve zvolme~$H$ tak, aby se~$d$ vyrovnalo s~$L^{1/d}/H$. Tedy $H = L^{1/d}/d$. -Celý výraz tím zjednodu¹íme na $\O(d + \log\,(L^{1/d}/d))$ = -$\O(d + 1/d\cdot\log L - \log d) = \O(d + 1/d\cdot\log L)$. Oba sèítance volbou -$d=\sqrt{\log L}$ vyrovnáme. +CelĂ˝ vĂ˝raz tĂ­m zjednoduĹĄĂ­me na $\O(d + \log\,(L^{1/d}/d))$ = +$\O(d + 1/d\cdot\log L - \log d) = \O(d + 1/d\cdot\log L)$. Oba sčítance volbou +$d=\sqrt{\log L}$ vyrovnĂĄme. -HOT Queue tedy zvládne \ s~amortizovanou èasovou slo¾itostí $\O(\sqrt{\log L})$ -a ostatní operace v~èase amortizovanì konstantním. Pou¾ijeme-li tuto strukturu -v~Dijkstrovì algoritmu, spoète vzdálenosti v~èase $\O(m + n\sqrt{\log L})$. +HOT Queue tedy zvlĂĄdne \ s~amortizovanou časovou sloĹžitostĂ­ $\O(\sqrt{\log L})$ +a ostatnĂ­ operace v~čase amortizovaně konstantnĂ­m. PouĹžijeme-li tuto strukturu +v~Dijkstrově algoritmu, spočte vzdĂĄlenosti v~čase $\O(m + n\sqrt{\log L})$. -\h{Dinicùv algoritmus} +\h{DinicĹŻv algoritmus} -Zajímavé vylep¹ení Dijkstrova algoritmu navrhl Dinic. V¹iml si, ¾e pokud -je ka¾dá hrana dlouhá alespoò~$\delta$, mù¾eme uzavírat nejen -vrchol s~minimálním ohodnocením~$\mu$, ale i v¹echny s~ohodnocením -men¹ím ne¾ $\mu+\delta$. +ZajĂ­mavĂŠ vylepĹĄenĂ­ Dijkstrova algoritmu navrhl Dinic. VĹĄiml si, Ĺže pokud +je kaĹždĂĄ hrana dlouhĂĄ alespoň~$\delta$, mĹŻĹžeme uzavĂ­rat nejen +vrchol s~minimĂĄlnĂ­m ohodnocenĂ­m~$\mu$, ale i vĹĄechny s~ohodnocenĂ­m +menĹĄĂ­m neĹž $\mu+\delta$. -Pro takto upravený Dijkstrùv algoritmus bude stále platit, ¾e pøi uzavírání -vrcholu odpovídá ohodnocení skuteèné vzdálenosti, tak¾e uzavøené vrcholy ji¾ -nejsou znovu otevírány. +Pro takto upravenĂ˝ DijkstrĹŻv algoritmus bude stĂĄle platit, Ĺže při uzavĂ­rĂĄnĂ­ +vrcholu odpovĂ­dĂĄ ohodnocenĂ­ skutečnĂŠ vzdĂĄlenosti, takĹže uzavřenĂŠ vrcholy jiĹž +nejsou znovu otevĂ­rĂĄny. -O~monotonii vzdáleností jsme sice pøi¹li, ale v~pøihrádkové struktuøe nebo -haldì mù¾eme klíèe nahradit hodnotami $h'(v) := \lfloor h(v)/\delta \rfloor$. -Tyto hodnoty se toti¾ chovají monotónnì a vrcholy se stejným $h'(v)$ mù¾eme -libovolnì zamìòovat. +O~monotonii vzdĂĄlenostĂ­ jsme sice přiĹĄli, ale v~přihrĂĄdkovĂŠ struktuře nebo +haldě mĹŻĹžeme klíče nahradit hodnotami $h'(v) := \lfloor h(v)/\delta \rfloor$. +Tyto hodnoty se totiĹž chovajĂ­ monotĂłnně a vrcholy se stejnĂ˝m $h'(v)$ mĹŻĹžeme +libovolně zaměňovat. -Kteroukoli z~popsaných pøihrádkových struktur mù¾eme tedy pou¾ít, pouze -v~rozboru èasové slo¾itosti nahradíme~$L$ výrazem $L/\delta$. Tento pøístup -pøitom funguje i pro neceloèíselné délky hran, pouze potøebujeme mít pøedem -k~dispozici netriviální dolní odhad na~v¹echny délky. +Kteroukoli z~popsanĂ˝ch přihrĂĄdkovĂ˝ch struktur mĹŻĹžeme tedy pouŞít, pouze +v~rozboru časovĂŠ sloĹžitosti nahradĂ­me~$L$ vĂ˝razem $L/\delta$. Tento přístup +přitom funguje i pro neceločíselnĂŠ dĂŠlky hran, pouze potřebujeme mĂ­t předem +k~dispozici netriviĂĄlnĂ­ dolnĂ­ odhad na~vĹĄechny dĂŠlky. -\h{Potenciály} +\h{PotenciĂĄly} -Vidìli jsme, ¾e v~grafech s~nezápornými délkami hran se nejkrat¹í cesty -hledají snáze. Nabízí se nalézt nìjakou transformaci, která by -dovedla délky hran upravit tak, aby byly nejkrat¹í cesty zachovány (samozøejmì -ne jejich délky, ale alespoò to, které cesty jsou nejkrat¹í). Nabízí se -následující fyzikální inspirace: +Viděli jsme, Ĺže v~grafech s~nezĂĄpornĂ˝mi dĂŠlkami hran se nejkratĹĄĂ­ cesty +hledajĂ­ snĂĄze. NabĂ­zĂ­ se nalĂŠzt nějakou transformaci, kterĂĄ by +dovedla dĂŠlky hran upravit tak, aby byly nejkratĹĄĂ­ cesty zachovĂĄny (samozřejmě +ne jejich dĂŠlky, ale alespoň to, kterĂŠ cesty jsou nejkratĹĄĂ­). NabĂ­zĂ­ se +nĂĄsledujĂ­cĂ­ fyzikĂĄlnĂ­ inspirace: -\s{Definice:} {\I Potenciál} budeme øíkat libovolné funkci $\psi: V\rightarrow {\bb R}$. -Pro ka¾dý potenciál zavedeme {\I redukované délky hran} $\ell_\psi(u,v) := \ell(u,v) + \psi(u) - \psi(v)$. -Potenciál nazveme {\I pøípustný,} pokud ¾ádná hrana nemá zápornou redukovanou délku. +\s{Definice:} {\I PotenciĂĄl} budeme říkat libovolnĂŠ funkci $\psi: V\rightarrow {\bb R}$. +Pro kaĹždĂ˝ potenciĂĄl zavedeme {\I redukovanĂŠ dĂŠlky hran} $\ell_\psi(u,v) := \ell(u,v) + \psi(u) - \psi(v)$. +PotenciĂĄl nazveme {\I přípustnĂ˝,} pokud ŞådnĂĄ hrana nemĂĄ zĂĄpornou redukovanou dĂŠlku. -\s{Pozorování:} Pro redukovanou délku libovolné cesty~$P$ z~$u$ do~$v$ platí: $\ell_\psi(P) = \ell(P) + \psi(u) - \psi(v)$. +\s{PozorovĂĄnĂ­:} Pro redukovanou dĂŠlku libovolnĂŠ cesty~$P$ z~$u$ do~$v$ platĂ­: $\ell_\psi(P) = \ell(P) + \psi(u) - \psi(v)$. \proof -Nech» cesta~$P$ prochází pøes vrcholy $u=w_1,\ldots,w_k=v$. Potom: +NechĹĽ cesta~$P$ prochĂĄzĂ­ přes vrcholy $u=w_1,\ldots,w_k=v$. Potom: $$ \ell_\psi(P) = \sum_i \ell_\psi(w_i,w_{i+1}) = \sum_i \left( \ell(w_i,w_{i+1}) + \psi(w_i) - \psi(w_{i+1}) \right). $$ -Tato suma je ov¹em teleskopická, tak¾e z~ní zbude +Tato suma je ovĹĄem teleskopickĂĄ, takĹže z~nĂ­ zbude $$ \sum_i\ell(w_i,w_{i+1}) + \psi(w_1) - \psi(w_k) = \ell(P) + \psi(u) - \psi(v). $$ \vskip-\baselineskip \qed -\s{Dùsledek:} Potenciálovou redukcí se délky v¹ech cest mezi~$u$ a~$v$ -zmìní o~tuté¾ konstantu, tak¾e struktura nejkrat¹ích cest zùstane nezmìnìna. +\s{DĹŻsledek:} PotenciĂĄlovou redukcĂ­ se dĂŠlky vĹĄech cest mezi~$u$ a~$v$ +změnĂ­ o~tutĂŠĹž konstantu, takĹže struktura nejkratĹĄĂ­ch cest zĹŻstane nezměněna. -Zbývá pøijít na~to, kde si obstarat nìjaký pøípustný potenciál. Pøidejme do~grafu -nový vrchol~$z$, pøiveïme z~nìj hrany nulové délky do~v¹ech ostatních vrcholù -a~oznaème~$\psi(v)$ vzdálenost ze~$z$ do~$v$ v~tomto grafu. Aby byl tento potenciál -pøípustný, musí pro ka¾dou hranu $uv$ platit $\ell_\psi(u,v) = \ell(u,v) + \psi(u) - \psi(v) \ge 0$. -Tuto nerovnost mù¾eme upravit na $\ell(u,v) + d(z,u) - d(z,v) \ge 0$, èili -$d(z,u) + \ell(u,v) \ge d(z,v)$, co¾ je ale obyèejná trojúhelníková nerovnost -pro vzdálenost v~grafu, která jistì platí. +ZbĂ˝vĂĄ přijĂ­t na~to, kde si obstarat nějakĂ˝ přípustnĂ˝ potenciĂĄl. Přidejme do~grafu +novĂ˝ vrchol~$z$, přiveďme z~něj hrany nulovĂŠ dĂŠlky do~vĹĄech ostatnĂ­ch vrcholĹŻ +a~označme~$\psi(v)$ vzdĂĄlenost ze~$z$ do~$v$ v~tomto grafu. Aby byl tento potenciĂĄl +přípustnĂ˝, musĂ­ pro kaĹždou hranu $uv$ platit $\ell_\psi(u,v) = \ell(u,v) + \psi(u) - \psi(v) \ge 0$. +Tuto nerovnost mĹŻĹžeme upravit na $\ell(u,v) + d(z,u) - d(z,v) \ge 0$, čili +$d(z,u) + \ell(u,v) \ge d(z,v)$, coĹž je ale obyčejnĂĄ trojĂşhelnĂ­kovĂĄ nerovnost +pro vzdĂĄlenost v~grafu, kterĂĄ jistě platĂ­. -Jedním výpoètem nejkrat¹ích cest v~grafu se zápornými hranami (tøeba algoritmem BFM) -tedy doká¾eme spoèítat potenciál, který nám poslou¾í k~redukci v¹ech hran na~nezáporné -délky. To nám samozøejmì nepomù¾e, chceme-li jednorázovì hledat nejkrat¹í cestu, -ale mù¾e nám to výraznì zjednodu¹it dal¹í, slo¾itìj¹í práci s~grafem. Jak uvidíme -v~pøí¹tí kapitole, mù¾eme tak napøíklad nalézt vzdálenosti mezi v¹emi dvojicemi -vrcholù v~èase $\O(nm + n^2\log n)$. +JednĂ­m vĂ˝počtem nejkratĹĄĂ­ch cest v~grafu se zĂĄpornĂ˝mi hranami (třeba algoritmem BFM) +tedy dokĂĄĹžeme spočítat potenciĂĄl, kterĂ˝ nĂĄm poslouŞí k~redukci vĹĄech hran na~nezĂĄpornĂŠ +dĂŠlky. To nĂĄm samozřejmě nepomĹŻĹže, chceme-li jednorĂĄzově hledat nejkratĹĄĂ­ cestu, +ale mĹŻĹže nĂĄm to vĂ˝razně zjednoduĹĄit dalĹĄĂ­, sloĹžitějĹĄĂ­ prĂĄci s~grafem. Jak uvidĂ­me +v~příštĂ­ kapitole, mĹŻĹžeme tak například nalĂŠzt vzdĂĄlenosti mezi vĹĄemi dvojicemi +vrcholĹŻ v~čase $\O(nm + n^2\log n)$. -Na~závìr tohoto oddílu doká¾eme jedno pomocné tvrzení o~potenciálech, které -nám pomù¾e v~konstrukci algoritmù typu \ppsp: +Na~zĂĄvěr tohoto oddĂ­lu dokĂĄĹžeme jedno pomocnĂŠ tvrzenĂ­ o~potenciĂĄlech, kterĂŠ +nĂĄm pomĹŻĹže v~konstrukci algoritmĹŻ typu \ppsp: -\s{Lemma:} Pokud $f$ a~$g$ jsou pøípustné potenciály, pak jsou jimi i: +\s{Lemma:} Pokud $f$ a~$g$ jsou přípustnĂŠ potenciĂĄly, pak jsou jimi i: \numlist\ndotted -\:konvexní kombinace $f$ a~$g$, tedy $\alpha f + \beta g$ pro libovolné $\alpha,\beta\ge 0, \alpha+\beta=1$; +\:konvexnĂ­ kombinace $f$ a~$g$, tedy $\alpha f + \beta g$ pro libovolnĂŠ $\alpha,\beta\ge 0, \alpha+\beta=1$; \:$\min(f,g)$; \:$\max(f,g)$. \endlist -\proof Buï $uv$ hrana. Potom z~definice pøípustnosti platí $\ell(u,v) \ge f(v) - f(u)$ a $\ell(u,v) \ge g(v) - g(u)$. -Jednotlivé èásti tvrzení doká¾eme takto: +\proof Buď $uv$ hrana. Potom z~definice přípustnosti platĂ­ $\ell(u,v) \ge f(v) - f(u)$ a $\ell(u,v) \ge g(v) - g(u)$. +JednotlivĂŠ části tvrzenĂ­ dokĂĄĹžeme takto: \numlist\ndotted -\:Pokud obì strany nerovnosti pro~$f$ vynásobíme konstantou~$\alpha$, u~nerovnosti pro~$g$ - konstantou~$\beta$ a obì nerovnosti seèteme, dostaneme: +\:Pokud obě strany nerovnosti pro~$f$ vynĂĄsobĂ­me konstantou~$\alpha$, u~nerovnosti pro~$g$ + konstantou~$\beta$ a obě nerovnosti sečteme, dostaneme: $$ (\alpha+\beta) \cdot \ell(u,v) \ge (\alpha f(v) + \beta g(v)) - (\alpha f(u) + \beta g(u)), $$ - co¾ je pøesnì po¾adovaná nerovnost pro pøípustnost funkce $\alpha f+\beta g$. -\:Oznaème $h := \min(f,g)$. Nech» bez újmy na obecnosti $f(u)\le g(u)$. Pokud také platí $f(v)\le g(v)$, - shoduje se minimum s~funkcí~$f$ a není co dokazovat. V~opaèném pøípadì je $h(u) = f(u)$, $h(v) = g(v)$. - Tehdy si staèí v¹imnout, ¾e $h(v) - h(u) = g(v) - f(u) < f(v) - f(u) \le \ell(u,v)$, tak¾e - potenciál~$h$ je pøípustný. -\:Doká¾eme analogicky. + coĹž je přesně poĹžadovanĂĄ nerovnost pro přípustnost funkce $\alpha f+\beta g$. +\:Označme $h := \min(f,g)$. NechĹĽ bez Ăşjmy na obecnosti $f(u)\le g(u)$. Pokud takĂŠ platĂ­ $f(v)\le g(v)$, + shoduje se minimum s~funkcĂ­~$f$ a nenĂ­ co dokazovat. V~opačnĂŠm případě je $h(u) = f(u)$, $h(v) = g(v)$. + Tehdy si stačí vĹĄimnout, Ĺže $h(v) - h(u) = g(v) - f(u) < f(v) - f(u) \le \ell(u,v)$, takĹže + potenciĂĄl~$h$ je přípustnĂ˝. +\:DokĂĄĹžeme analogicky. \qeditem \endlist -\h{Algoritmy pro problém typu \ppsp} - -Zamìøme se nyní na~pøípad, kdy chceme hledat nejkrat¹í cesty mezi zadanou dvojicí -vrcholù $s$,~$t$. Obvykle se i v~této situaci pou¾ívají algoritmy \sssp{} (SSSP) a v~obecném -pøípadì ani není efektivnìj¹í øe¹ení známo. Existuje ov¹em velké mno¾ství heuristik, kterými -lze obvykle výpoèet zrychlit. Nìkteré z~nich si pøedvedeme na Dijkstrovì algoritmu. - -Dijkstrùv algoritmus ve~své klasické podobì neví vùbec nic o~cílovém vrcholu a -prohledá celý graf. Hned se nabízí vyu¾ít toho, ¾e od~okam¾iku uzavøení -kteréhokoliv vrcholu se ji¾ jeho ohodnocení nezmìní. Pokud tedy uzavøeme cílový -vrchol, mù¾eme se zastavit. - -Jakou èást grafu prohledáváme teï? V~metrice dané vzdálenostmi v~grafu je to nejmen¹í -koule se støedem ve~vrcholu~$u$, která obsahuje nejkrat¹í cestu (dobøe se to -pøedstavuje na~hledání v~silnièní síti na~rovinné mapì). - -Také mù¾eme spustit prohledávání z~obou koncù zároveò, tedy zkombinovat hledání -od~$s$ v~pùvodním grafu s~hledáním od~$t$ v~grafu s~obrácenou orientací hran. -Oba postupy mù¾eme libovolnì støídat a zastavíme se v~okam¾iku, kdy jsme jeden -vrchol uzavøeli v~obou smìrech. Pozor ov¹em na to, ¾e souèet obou ohodnocení -tohoto vrcholu nemusí být roven $d(v,u)$ -- zkuste vymyslet protipøíklad. -Nejkrat¹í cesta je¹tì mù¾e vypadat tak, ¾e pøechází po nìjaké hranì mezi vrcholem -uzavøeným v~jednom smìru a vrcholem uzavøeným ve~smìru druhém (ponechme bez dùkazu). -Staèí tedy bìhem relaxace zjistit, zda je konec hrany uzavøený v~opaèném -smìru prohledávání, a~pokud ano, zapoèítat cestu do~prùbì¾ného minima. - -Obousmìrný Dijkstrùv algoritmus projde sjednocení nìjaké koule okolo~$s$ s~nìjakou -koulí okolo~$t$, které obsahuje nejkrat¹í cestu. Prùmìry koulí pøitom závisí na tom, -jak budeme bìhem výpoètu støídat oba smìry prohledávání. V~nejhor¹ím pøípadì samozøejmì -mù¾eme prohledat celý graf. +\h{Algoritmy pro problĂŠm typu \ppsp} + +Zaměřme se nynĂ­ na~případ, kdy chceme hledat nejkratĹĄĂ­ cesty mezi zadanou dvojicĂ­ +vrcholĹŻ $s$,~$t$. Obvykle se i v~tĂŠto situaci pouŞívajĂ­ algoritmy \sssp{} (SSSP) a v~obecnĂŠm +případě ani nenĂ­ efektivnějĹĄĂ­ řeĹĄenĂ­ znĂĄmo. Existuje ovĹĄem velkĂŠ mnoĹžstvĂ­ heuristik, kterĂ˝mi +lze obvykle vĂ˝počet zrychlit. NěkterĂŠ z~nich si předvedeme na Dijkstrově algoritmu. + +DijkstrĹŻv algoritmus ve~svĂŠ klasickĂŠ podobě nevĂ­ vĹŻbec nic o~cĂ­lovĂŠm vrcholu a +prohledĂĄ celĂ˝ graf. Hned se nabĂ­zĂ­ vyuŞít toho, Ĺže od~okamĹžiku uzavřenĂ­ +kterĂŠhokoliv vrcholu se jiĹž jeho ohodnocenĂ­ nezměnĂ­. Pokud tedy uzavřeme cĂ­lovĂ˝ +vrchol, mĹŻĹžeme se zastavit. + +Jakou část grafu prohledĂĄvĂĄme teď? V~metrice danĂŠ vzdĂĄlenostmi v~grafu je to nejmenĹĄĂ­ +koule se středem ve~vrcholu~$u$, kterĂĄ obsahuje nejkratĹĄĂ­ cestu (dobře se to +představuje na~hledĂĄnĂ­ v~silničnĂ­ sĂ­ti na~rovinnĂŠ mapě). + +TakĂŠ mĹŻĹžeme spustit prohledĂĄvĂĄnĂ­ z~obou koncĹŻ zĂĄroveň, tedy zkombinovat hledĂĄnĂ­ +od~$s$ v~pĹŻvodnĂ­m grafu s~hledĂĄnĂ­m od~$t$ v~grafu s~obrĂĄcenou orientacĂ­ hran. +Oba postupy mĹŻĹžeme libovolně střídat a zastavĂ­me se v~okamĹžiku, kdy jsme jeden +vrchol uzavřeli v~obou směrech. Pozor ovĹĄem na to, Ĺže součet obou ohodnocenĂ­ +tohoto vrcholu nemusĂ­ bĂ˝t roven $d(v,u)$ -- zkuste vymyslet protipříklad. +NejkratĹĄĂ­ cesta jeĹĄtě mĹŻĹže vypadat tak, Ĺže přechĂĄzĂ­ po nějakĂŠ hraně mezi vrcholem +uzavřenĂ˝m v~jednom směru a vrcholem uzavřenĂ˝m ve~směru druhĂŠm (ponechme bez dĹŻkazu). +Stačí tedy během relaxace zjistit, zda je konec hrany uzavřenĂ˝ v~opačnĂŠm +směru prohledĂĄvĂĄnĂ­, a~pokud ano, započítat cestu do~prĹŻběžnĂŠho minima. + +ObousměrnĂ˝ DijkstrĹŻv algoritmus projde sjednocenĂ­ nějakĂŠ koule okolo~$s$ s~nějakou +koulĂ­ okolo~$t$, kterĂŠ obsahuje nejkratĹĄĂ­ cestu. PrĹŻměry koulĂ­ přitom zĂĄvisĂ­ na tom, +jak budeme během vĂ˝počtu střídat oba směry prohledĂĄvĂĄnĂ­. V~nejhorĹĄĂ­m případě samozřejmě +mĹŻĹžeme prohledat celĂ˝ graf. \h{Algoritmus \astar} -V~umìlé inteligenci se èasto pro hledání nejkrat¹í cesty v~rozsáhlých grafech -(obvykle stavových prostorech úloh) pou¾ívá algoritmus nazývaný~\astar{} \cite{hart:astar}. -Jedná se o~modifikaci Dijkstrova algoritmu, která vyu¾ívá heuristickou funkci -pro dolní odhad vzdálenosti do~cíle; oznaème si ji $\psi(v)$. V~ka¾dém kroku pak uzavíra -vrchol~$v$ s~nejmen¹ím mo¾ným souètem $h(v)+\psi(v)$ aktuálního ohodnocení s~heuristikou. +V~umělĂŠ inteligenci se často pro hledĂĄnĂ­ nejkratĹĄĂ­ cesty v~rozsĂĄhlĂ˝ch grafech +(obvykle stavovĂ˝ch prostorech Ăşloh) pouŞívĂĄ algoritmus nazĂ˝vanĂ˝~\astar{} \cite{hart:astar}. +JednĂĄ se o~modifikaci Dijkstrova algoritmu, kterĂĄ vyuŞívĂĄ heuristickou funkci +pro dolnĂ­ odhad vzdĂĄlenosti do~cĂ­le; označme si ji $\psi(v)$. V~kaĹždĂŠm kroku pak uzavĂ­ra +vrchol~$v$ s~nejmenĹĄĂ­m moĹžnĂ˝m součtem $h(v)+\psi(v)$ aktuĂĄlnĂ­ho ohodnocenĂ­ s~heuristikou. -Intuice za tímto algoritmem je jasná: pokud víme, ¾e nìjaký vrchol je blízko -od~poèátaèního vrcholu~$s$, ale bude z~nìj urèitì daleko do cíle~$t$, zatím ho -odlo¾íme a budeme zkoumat nadìjnìj¹í varianty. +Intuice za tĂ­mto algoritmem je jasnĂĄ: pokud vĂ­me, Ĺže nějakĂ˝ vrchol je blĂ­zko +od~počátačnĂ­ho vrcholu~$s$, ale bude z~něj určitě daleko do cĂ­le~$t$, zatĂ­m ho +odloŞíme a budeme zkoumat nadějnějĹĄĂ­ varianty. -Heuristika se pøitom volí podle konkrétního problému -- napø. hledáme-li cestu -v~mapì, mù¾eme pou¾ít vzdálenost do~cíle vzdu¹nou èarou. +Heuristika se přitom volĂ­ podle konkrĂŠtnĂ­ho problĂŠmu -- např. hledĂĄme-li cestu +v~mapě, mĹŻĹžeme pouŞít vzdĂĄlenost do~cĂ­le vzduĹĄnou čarou. -Je u~tohoto algoritmu zaruèeno, ¾e v¾dy najde nejkrat¹í cestu? Na to nám dá odpovìï -teorie potenciálù: +Je u~tohoto algoritmu zaručeno, Ĺže vĹždy najde nejkratĹĄĂ­ cestu? Na to nĂĄm dĂĄ odpověď +teorie potenciĂĄlĹŻ: -\s{Vìta:} Bìh algoritmu \astar{} odpovídá prùbìhu Dijkstrova algoritmu -na~grafu redukovaném potenciálem~$-\psi$. Pøesnìji, -pokud oznaèíme $h^*$ aktuální ohodnocení v~\astar{} a $h$ aktuální ohodnocení -v~synchronnì bì¾ícím Dijkstrovi, bude v¾dy platit $h(v) = h^*(v) - \psi(s) + \psi(v)$. +\s{Věta:} Běh algoritmu \astar{} odpovĂ­dĂĄ prĹŻběhu Dijkstrova algoritmu +na~grafu redukovanĂŠm potenciĂĄlem~$-\psi$. Přesněji, +pokud označíme $h^*$ aktuĂĄlnĂ­ ohodnocenĂ­ v~\astar{} a $h$ aktuĂĄlnĂ­ ohodnocenĂ­ +v~synchronně běžícĂ­m Dijkstrovi, bude vĹždy platit $h(v) = h^*(v) - \psi(s) + \psi(v)$. \proof -Indukcí podle doby bìhu obou algoritmù. Na poèátku je $h^*(s)$ i $h(s)$ nulové -a v¹echna ostatní $h^*$ a~$h$ jsou nekoneèná, tak¾e tvrzení platí. V~ka¾dém dal¹ím -kroku \astar{} vybere vrchol~$v$ s~nejmen¹ím $h^*(v) + \psi(v)$, co¾ je tentý¾ vrchol, -který vybere Dijkstra ($\psi(s)$ je stále stejné). - -Uva¾ujme, co se stane bìhem relaxace hrany $vw$: Dijkstra se pokusí sní¾it ohodnocení $h(w)$ -o~$\delta = h(w) - h(v) - \ell_{-\psi}(v,w)$ a provede to, pokud $\delta>0$. Uká¾eme, -¾e \astar{} udìlá toté¾: +IndukcĂ­ podle doby běhu obou algoritmĹŻ. Na počátku je $h^*(s)$ i $h(s)$ nulovĂŠ +a vĹĄechna ostatnĂ­ $h^*$ a~$h$ jsou nekonečnĂĄ, takĹže tvrzenĂ­ platĂ­. V~kaĹždĂŠm dalĹĄĂ­m +kroku \astar{} vybere vrchol~$v$ s~nejmenĹĄĂ­m $h^*(v) + \psi(v)$, coĹž je tentýŞ vrchol, +kterĂ˝ vybere Dijkstra ($\psi(s)$ je stĂĄle stejnĂŠ). + +UvaĹžujme, co se stane během relaxace hrany $vw$: Dijkstra se pokusĂ­ snĂ­Ĺžit ohodnocenĂ­ $h(w)$ +o~$\delta = h(w) - h(v) - \ell_{-\psi}(v,w)$ a provede to, pokud $\delta>0$. UkĂĄĹžeme, +Ĺže \astar{} udělĂĄ totĂŠĹž: $$\eqalign{ \delta &= (h^*(w) - \psi(s) + \psi(w)) - (h^*(v) - \psi(s) + \psi(v)) - (\ell(v,w) - \psi(v) + \psi(w)) \cr &= h^*(w) - \psi(s) + \psi(w) - h^*(v) + \psi(s) - \psi(v) - \ell(v,w) + \psi(v) - \psi(w) \cr &= h^*(w) - h^*(v) - \ell(v,w). }$$ -Oba algoritmy tedy a¾ na~posunutí dané potenciálem poèítají toté¾. +Oba algoritmy tedy aĹž na~posunutĂ­ danĂŠ potenciĂĄlem počítajĂ­ totĂŠĹž. \qed -\s{Dùsledek:} Algoritmus \astar{} funguje jen tehdy, je-li potenciál $-\psi$ pøípustný. +\s{DĹŻsledek:} Algoritmus \astar{} funguje jen tehdy, je-li potenciĂĄl $-\psi$ přípustnĂ˝. -Napøíklad pro rovinnou mapu to heuristika daná euklidovskou vzdáleností~$\varrho$, tedy $\psi(v) := \varrho(v,t)$, splòuje: -Pøípustnost po¾aduje pro ka¾dou hranu $uv$ nerovnost +Například pro rovinnou mapu to heuristika danĂĄ euklidovskou vzdĂĄlenostĂ­~$\varrho$, tedy $\psi(v) := \varrho(v,t)$, splňuje: +Přípustnost poĹžaduje pro kaĹždou hranu $uv$ nerovnost $\ell(u,v) - \psi(v) + \psi(u) \ge 0$, tedy $\ell(u,v) - \varrho(v,t) + \varrho(u,t) \ge 0$. -Jeliko¾ $\ell(u,v) \ge \varrho(u,v)$, -staèí dokázat, ¾e $\varrho(u,v) - \varrho(v,t) + \varrho(u,t) \ge 0$, -co¾ je ov¹em trojúhelníková nerovnost pro metriku~$\varrho$. +JelikoĹž $\ell(u,v) \ge \varrho(u,v)$, +stačí dokĂĄzat, Ĺže $\varrho(u,v) - \varrho(v,t) + \varrho(u,t) \ge 0$, +coĹž je ovĹĄem trojĂşhelnĂ­kovĂĄ nerovnost pro metriku~$\varrho$. \references \bye diff --git a/14-floyd/14-floyd.tex b/14-floyd/14-floyd.tex index 264da1a..50c24a4 100644 --- a/14-floyd/14-floyd.tex +++ b/14-floyd/14-floyd.tex @@ -1,273 +1,273 @@ \input ../sgr.tex -\prednaska{14}{Transitivní uzávìry}{} - -V~pøedchozí kapitole jsme se zabývali algoritmy pro hledání nejkrat¹ích -cest z~daného poèáteèního vrcholu. Nyní se zamìøíme na pøípady, kdy nás -zajímají vzdálenosti, pøípadnì pouhá dosa¾itelnost, mezi v¹emi dvojicemi -vrcholù. - -Výstupem takového algoritmu bude {\I matice vzdáleností} (pøípadnì -{\I matice dosa¾itelnosti}). Na ni se také mu¾eme dívat jako na {\I transitivní -uzávìr} zadaného grafu -- to je graf na~té¾e mno¾inì vrcholù, jeho¾ hrany -odpovídají nejkrat¹ím cestám v~grafu pùvodním. - -Jeden zpùsob, jak transitivní uzávìr spoèítat, se ihned nabízí: postupnì -spustit Dijkstrùv algoritmus pro v¹echny mo¾né volby poèáteèního vrcholu, -pøípadnì se pøed tím je¹tì zbavit záporných hran pomocí potenciálù. Tak -dosáhneme èasové slo¾itosti $\O(mn + n^2\log n)$. To je pro øídké grafy -nejlep¹í známý výsledek -- jen $\O(\log n)$-krát pomalej¹í, ne¾ je velikost -výstupu. - -Je-li graf hustý, pracují obvykle rychleji algoritmy zalo¾ené na maticích, zejména -na jejich násobení. Nìkolik algoritmù tohoto druhu si nyní pøedvedeme, -a to jak pro výpoèet vzdáleností, tak pro dosa¾itelnost. - -Graf na vstupu bude v¾dy zadán maticí délek hran -- to je matice $n\times n$, -její¾ øádky i sloupce jsou indexované vrcholy a na pozici $(i,j)$ se nachází -délka hrany $ij$; pøípadné chybìjící hrany doplníme s~délkou~$+\infty$. - -\h{Floydùv-Warshallùv algoritmus} - -Zaènìme algoritmem, který nezávisle na sobì objevili Floyd a Warshall. -Funguje pro libovolný orientovaný graf bez záporných cyklù. - -Oznaème $D^k_{ij}$ délku nejkrat¹í cesty z~vrcholu~$i$ do vrcholu~$j$ pøes -vrcholy 1 a¾~$k$ (tím myslíme, ¾e v¹echny vnitøní vrcholy cesty le¾í v~mno¾inì $\{1,\ldots,k\}$). -Jako obvykle polo¾íme $D^k_{ij}=+\infty$, pokud ¾ádná taková cesta neexistuje. -Pak platí: +\prednaska{14}{Transitivní uzávěry}{} + +V~předchozí kapitole jsme se zabývali algoritmy pro hledání nejkratších +cest z~daného počátečního vrcholu. Nyní se zaměříme na případy, kdy nás +zajímají vzdálenosti, případně pouhá dosažitelnost, mezi vÅ¡emi dvojicemi +vrcholů. + +Výstupem takového algoritmu bude {\I matice vzdáleností} (případně +{\I matice dosažitelnosti}). Na ni se také mužeme dívat jako na {\I transitivní +uzávěr} zadaného grafu -- to je graf na~téže množině vrcholů, jehož hrany +odpovídají nejkratším cestám v~grafu původním. + +Jeden způsob, jak transitivní uzávěr spočítat, se ihned nabízí: postupně +spustit Dijkstrův algoritmus pro vÅ¡echny možné volby počátečního vrcholu, +případně se před tím jeÅ¡tě zbavit záporných hran pomocí potenciálů. Tak +dosáhneme časové složitosti $\O(mn + n^2\log n)$. To je pro řídké grafy +nejlepší známý výsledek -- jen $\O(\log n)$-krát pomalejší, než je velikost +výstupu. + +Je-li graf hustý, pracují obvykle rychleji algoritmy založené na maticích, zejména +na jejich násobení. Několik algoritmů tohoto druhu si nyní předvedeme, +a to jak pro výpočet vzdáleností, tak pro dosažitelnost. + +Graf na vstupu bude vždy zadán maticí délek hran -- to je matice $n\times n$, +jejíž řádky i sloupce jsou indexované vrcholy a na pozici $(i,j)$ se nachází +délka hrany $ij$; případné chybějící hrany doplníme s~délkou~$+\infty$. + +\h{Floydův-Warshallův algoritmus} + +Začněme algoritmem, který nezávisle na sobě objevili Floyd a Warshall. +Funguje pro libovolný orientovaný graf bez záporných cyklů. + +Označme $D^k_{ij}$ délku nejkratší cesty z~vrcholu~$i$ do vrcholu~$j$ přes +vrcholy 1 až~$k$ (tím myslíme, že vÅ¡echny vnitřní vrcholy cesty leží v~množině $\{1,\ldots,k\}$). +Jako obvykle položíme $D^k_{ij}=+\infty$, pokud žádná taková cesta neexistuje. +Pak platí: $$\eqalign{ -D^0_{ij} &= \hbox{délka hrany $ij$,} \cr -D^n_{ij} &= \hbox{hledaná vzdálenost z~$i$ do~$j$,} \cr +D^0_{ij} &= \hbox{délka hrany $ij$,} \cr +D^n_{ij} &= \hbox{hledaná vzdálenost z~$i$ do~$j$,} \cr D^k_{ij} &= \min( D^{k-1}_{ij}, D^{k-1}_{ik} + D^{k-1}_{kj} ). \cr }$$ -První dvì rovnosti plynou pøímo z~definice. Tøetí rovnost dostaneme rozdìlením -cest z~$i$ do~$j$ pøes 1 a¾~$k$ na ty, které se vrcholu~$k$ vyhnou (a~jsou tedy -cestami pøes 1 a¾~$k-1$), a ty, které ho pou¾ijí -- ka¾dou takovou mù¾eme slo¾it -z~cesty z~$i$ do~$k$ a cesty z~$k$ do~$j$, obojí pøes 1 a¾~$k-1$. +První dvě rovnosti plynou přímo z~definice. Třetí rovnost dostaneme rozdělením +cest z~$i$ do~$j$ přes 1 až~$k$ na ty, které se vrcholu~$k$ vyhnou (a~jsou tedy +cestami přes 1 až~$k-1$), a ty, které ho použijí -- každou takovou můžeme složit +z~cesty z~$i$ do~$k$ a cesty z~$k$ do~$j$, obojí přes 1 až~$k-1$. -Zbývá vyøe¹it jednu malièkost: slo¾ením cesty z~$i$ do~$k$ s~cestou z~$k$ do~$j$ -nemusí nutnì vzniknout cesta, proto¾e se nìjaký vrchol mù¾e opakovat. V~grafech -bez záporných cyklù nicménì takový sled nemù¾e být krat¹í ne¾ nejkrat¹í cesta, -tak¾e tím fale¹né øe¹ení nevyrobíme. (Pøesnìji: ze sledu $i\alpha v\beta k\gamma v\delta j$, -kde $v\not\in\beta,\gamma$, mù¾eme vypu¹tìním èásti $v\beta k\gamma v$ nezáporné -délky získat sled z~$i$ do~$j$ pøes 1 a¾~$k-1$, jeho¾ délka nemù¾e být men¹í -ne¾~$D^{k-1}_{ij}$.) +Zbývá vyřeÅ¡it jednu maličkost: složením cesty z~$i$ do~$k$ s~cestou z~$k$ do~$j$ +nemusí nutně vzniknout cesta, protože se nějaký vrchol může opakovat. V~grafech +bez záporných cyklů nicméně takový sled nemůže být kratší než nejkratší cesta, +takže tím faleÅ¡né řeÅ¡ení nevyrobíme. (Přesněji: ze sledu $i\alpha v\beta k\gamma v\delta j$, +kde $v\not\in\beta,\gamma$, můžeme vypuÅ¡těním části $v\beta k\gamma v$ nezáporné +délky získat sled z~$i$ do~$j$ přes 1 až~$k-1$, jehož délka nemůže být menší +než~$D^{k-1}_{ij}$.) -Samotný algoritmus postupnì poèítá matice $D^0, D^1, \ldots, D^n$ podle uvedeného pøedpisu: +Samotný algoritmus postupně počítá matice $D^0, D^1, \ldots, D^n$ podle uvedeného předpisu: \algo -\:$D^0 \leftarrow \hbox{matice délek hran}$. +\:$D^0 \leftarrow \hbox{matice délek hran}$. \:Pro $k=1,\ldots,n$: \::Pro $i,j=1,\ldots,n$: \:::$D^k_{ij} \leftarrow \min( D^{k-1}_{ij}, D^{k-1}_{ik} + D^{k-1}_{kj} )$. -\:$\hbox{Matice vzdáleností} \leftarrow D^n.$ +\:$\hbox{Matice vzdáleností} \leftarrow D^n.$ \endalgo -Èasová slo¾itost tohoto algoritmu èiní $\Theta(n^3)$. Kubickou prostorovou -slo¾itost mù¾eme snadno sní¾it na~kvadratickou: Buï si uvìdomíme, ¾e v~ka¾dém -okam¾iku potøebujeme jen aktuální matici~$D^k$ a pøedchozí~$D^{k-1}$. Anebo -nahlédneme, ¾e mù¾eme $D^{k-1}$ na~$D^k$ pøepisovat na místì. U~hodnot $D_{ik}$ -a~$D_{kj}$ je toti¾ podle definice stará i nová hodnota stejná. Algoritmu tedy -staèí jediné pole velikosti $n\times n$, které na~poèátku výpoètu obsahuje -vstup a na~konci výstup. +Časová složitost tohoto algoritmu činí $\Theta(n^3)$. Kubickou prostorovou +složitost můžeme snadno snížit na~kvadratickou: Buď si uvědomíme, že v~každém +okamžiku potřebujeme jen aktuální matici~$D^k$ a předchozí~$D^{k-1}$. Anebo +nahlédneme, že můžeme $D^{k-1}$ na~$D^k$ přepisovat na místě. U~hodnot $D_{ik}$ +a~$D_{kj}$ je totiž podle definice stará i nová hodnota stejná. Algoritmu tedy +stačí jediné pole velikosti $n\times n$, které na~počátku výpočtu obsahuje +vstup a na~konci výstup. -\h{Regulární výrazy} +\h{Regulární výrazy} -Pøedchozí algoritmus lze zajímavì zobecnit, toti¾ tak, aby pro ka¾dou dvojici -vrcholù sestrojil vhodnou reprezentaci mno¾iny v¹ech sledù vedoucích mezi nimi. -Tato reprezentace bude velice podobná regulárním výrazùm známým z~UNIXu -a z~teorie automatù. Budeme pøipou¹tìt orientované multigrafy se smyèkami -a násobnými hranami. +Předchozí algoritmus lze zajímavě zobecnit, totiž tak, aby pro každou dvojici +vrcholů sestrojil vhodnou reprezentaci množiny vÅ¡ech sledů vedoucích mezi nimi. +Tato reprezentace bude velice podobná regulárním výrazům známým z~UNIXu +a z~teorie automatů. Budeme připouÅ¡tět orientované multigrafy se smyčkami +a násobnými hranami. -\s{Definice:} {\I Svazek} je mno¾ina sledù, které mají spoleèný poèáteèní -a koncový vrchol. {\I Typem} svazku nazveme uspoøádanou dvojici tìchto vrcholù. -Místo \uv{svazek typu $(u,v)$} budeme obvykle øíkat prostì {\I $uv$-svazek.} +\s{Definice:} {\I Svazek} je množina sledů, které mají společný počáteční +a koncový vrchol. {\I Typem} svazku nazveme uspořádanou dvojici těchto vrcholů. +Místo \uv{svazek typu $(u,v)$} budeme obvykle říkat prostě {\I $uv$-svazek.} -Triviálními pøípady svazkù jsou prázdná mno¾ina~$\emptyset$, samotná hrana~$uv$ a pro -$u=v$ také sled~$\varepsilon_u$ nulové délky. Svazky mù¾eme kombinovat -tìmito operacemi: +Triviálními případy svazků jsou prázdná množina~$\emptyset$, samotná hrana~$uv$ a pro +$u=v$ také sled~$\varepsilon_u$ nulové délky. Svazky můžeme kombinovat +těmito operacemi: \itemize\ibull -\:$A\cup B$ -- {\I sjednocení} dvou svazkù tého¾ typu, -\:$AB$ nebo $A\cdot B$ -- {\I zøetìzení} $uv$-svazku~$A$ s~$vw$-svazkem~$B$: výsledkem je $uw$-svazek -obsahující v¹echna spojení sledu z~$A$ se sledem z~$B$, -\:$A^*$ -- {\I iterace} $uu$-svazku: výsledkem je $uu$-svazek -$\varepsilon \cup A \cup AA \cup AAA \cup \ldots$ (tedy v¹echna mo¾ná -spojení koneènì mnoha sledù z~$A$). +\:$A\cup B$ -- {\I sjednocení} dvou svazků téhož typu, +\:$AB$ nebo $A\cdot B$ -- {\I zřetězení} $uv$-svazku~$A$ s~$vw$-svazkem~$B$: výsledkem je $uw$-svazek +obsahující vÅ¡echna spojení sledu z~$A$ se sledem z~$B$, +\:$A^*$ -- {\I iterace} $uu$-svazku: výsledkem je $uu$-svazek +$\varepsilon \cup A \cup AA \cup AAA \cup \ldots$ (tedy vÅ¡echna možná +spojení konečně mnoha sledů z~$A$). \endlist -\>Ve~výrazu definujícím~$A^*$ jsme vyu¾ili, ¾e operace sjednocení a zøetìzení -jsou asociativní, tak¾e je nemusíme závorkovat. Navíc sjednocení má ve~výrazech -ni¾¹í prioritu ne¾ zøetìzení. +\>Ve~výrazu definujícím~$A^*$ jsme využili, že operace sjednocení a zřetězení +jsou asociativní, takže je nemusíme závorkovat. Navíc sjednocení má ve~výrazech +nižší prioritu než zřetězení. -\>Svazky budeme obvykle reprezentovat {\I sledovými výrazy,} co¾ jsou -výrazy koneèné délky sestávající z~triviálních svazkù a vý¹e uvedených -operací. +\>Svazky budeme obvykle reprezentovat {\I sledovými výrazy,} což jsou +výrazy konečné délky sestávající z~triviálních svazků a výše uvedených +operací. -\s{Pozorování:} Sledy mù¾eme reprezentovat øetìzci nad abecedou, její¾ -symboly jsou identifikátory hran. Sledové výrazy pak odpovídají regulárním -výrazùm nad touto abecedou. +\s{Pozorování:} Sledy můžeme reprezentovat řetězci nad abecedou, jejíž +symboly jsou identifikátory hran. Sledové výrazy pak odpovídají regulárním +výrazům nad touto abecedou. -Uká¾eme, jak pro v¹echny dvojice vrcholu $i,j$ sestrojit sledový výraz $R_{ij}$ -popisující svazek v¹ech sledù z~$i$ do~$j$. Podobnì jako u~Floydova-Warshallova -algoritmu zavedeme $R^k_{ij}$ coby výraz popisující sledy z~$i$ do~$j$ pøes 1 a¾~$k$ -a nahlédneme, ¾e platí: +Ukážeme, jak pro vÅ¡echny dvojice vrcholu $i,j$ sestrojit sledový výraz $R_{ij}$ +popisující svazek vÅ¡ech sledů z~$i$ do~$j$. Podobně jako u~Floydova-Warshallova +algoritmu zavedeme $R^k_{ij}$ coby výraz popisující sledy z~$i$ do~$j$ přes 1 až~$k$ +a nahlédneme, že platí: $$\eqalign{ R^0_{ij} &= \cases{ - \hbox{mno¾ina v¹ech hran z~$i$ do~$j$} & \hbox{pokud $i\ne j$} \cr + \hbox{množina vÅ¡ech hran z~$i$ do~$j$} & \hbox{pokud $i\ne j$} \cr \varepsilon_i & \hbox{pokud $i=j$} \cr } \cr -R^n_{ij} &= \hbox{hledané $R_{ij}$}, \cr +R^n_{ij} &= \hbox{hledané $R_{ij}$}, \cr R^k_{ij} &= R^{k-1}_{ij} \cup R^{k-1}_{ik}(R^{k-1}_{kk})^*R^{k-1}_{kj}. \cr }$$ -První dvì rovnosti opìt plynou pøímo z~definice (mno¾inu v¹ech hran zapí¹eme -buï jako prázdnou nebo ji vytvoøíme sjednocováním z~jednoprvkových mno¾in). Tøetí -rovnost vychází z~toho, ¾e ka¾dý sled z~$i$ do~$j$ buï neobsahuje~$k$, nebo ho -mù¾eme rozdìlit na~èásti mezi jednotlivými náv¹tìvami vrcholu~$k$. - -Algoritmus tedy bude postupnì budovat matice $R^0, R^1, \ldots, R^n$ podle tìchto -pravidel. Provedeme pøi tom $\Theta(n^3)$ operací, ov¹em s~výrazy, jejich¾ délka -mù¾e být a¾ øádovì~$4^n$. Radìji ne¾ jako øetìzce je proto budeme ukládat v~podobì -acyklických orientovaných grafù: vrcholy budou operace, hrany je budou pøipojovat -k~operandùm. - -K~pøímému pou¾ití se takový exponenciálnì dlouhý výraz hodí málokdy, ale mù¾e -nám pomoci odpovídat na rùzné otázky týkající se sledù s~danými koncovými vrcholy. -Máme-li nìjakou funkci~$f$ ohodnocující mno¾iny sledù kódované sledovými -výrazy, staèí umìt vyhodnotit: +První dvě rovnosti opět plynou přímo z~definice (množinu vÅ¡ech hran zapíšeme +buď jako prázdnou nebo ji vytvoříme sjednocováním z~jednoprvkových množin). Třetí +rovnost vychází z~toho, že každý sled z~$i$ do~$j$ buď neobsahuje~$k$, nebo ho +můžeme rozdělit na~části mezi jednotlivými návÅ¡těvami vrcholu~$k$. + +Algoritmus tedy bude postupně budovat matice $R^0, R^1, \ldots, R^n$ podle těchto +pravidel. Provedeme při tom $\Theta(n^3)$ operací, ovÅ¡em s~výrazy, jejichž délka +může být až řádově~$4^n$. Raději než jako řetězce je proto budeme ukládat v~podobě +acyklických orientovaných grafů: vrcholy budou operace, hrany je budou připojovat +k~operandům. + +K~přímému použití se takový exponenciálně dlouhý výraz hodí málokdy, ale může +nám pomoci odpovídat na různé otázky týkající se sledů s~danými koncovými vrcholy. +Máme-li nějakou funkci~$f$ ohodnocující množiny sledů kódované sledovými +výrazy, stačí umět vyhodnotit: \itemize\ibull -\:výsledek pro triviální výrazy $f(\emptyset)$, $f(\varepsilon)$ a $f(e)$ pro hranu~$e$, -\:hodnoty $f(\alpha\cup\beta)$, $f(\alpha\beta)$ a $f(\alpha^*)$, známe-li ji¾ $f(\alpha)$ a $f(\beta)$. +\:výsledek pro triviální výrazy $f(\emptyset)$, $f(\varepsilon)$ a $f(e)$ pro hranu~$e$, +\:hodnoty $f(\alpha\cup\beta)$, $f(\alpha\beta)$ a $f(\alpha^*)$, známe-li již $f(\alpha)$ a $f(\beta)$. \endlist -\>Pro výpoèet v¹ech $f(R_{ij})$ nám pak staèí $\Theta(n^3)$ vyhodnocení funkce~$f$. +\>Pro výpočet vÅ¡ech $f(R_{ij})$ nám pak stačí $\Theta(n^3)$ vyhodnocení funkce~$f$. -\s{Poznámka pro ctitele algebry:} Vý¹e uvedená konstrukce není nic jiného, ne¾ popis +\s{Poznámka pro ctitele algebry:} Výše uvedená konstrukce není nic jiného, než popis homomorfismu~$f$ z~algebry $({\cal S},\emptyset,\varepsilon_1,\ldots,\varepsilon_n, -e_1,\ldots,e_m,\cup,\cdot,{}^*)$ nad mno¾inou~${\cal S}$ v¹ech svazkù do~nìjaké -algebry $(X,{\bf 0},c_1,\ldots,c_n,h_1,\ldots,h_m,\oplus,\otimes,\circledast)$, kde~$X$ je mno¾ina -v¹ech ohodnocení sledù, {\bf 0}, $c_1,\ldots,c_n$ a $h_1,\ldots,h_m$ jsou konstanty, -$\oplus$ a~$\otimes$ binární operace a $\circledast$ unární operace. Prùbìh výpoètu -upraveného algoritmu je pak homomorfním obrazem prùbìhu výpoètu pùvodního algoritmu -pracujícího pøímo se svazky. +e_1,\ldots,e_m,\cup,\cdot,{}^*)$ nad množinou~${\cal S}$ vÅ¡ech svazků do~nějaké +algebry $(X,{\bf 0},c_1,\ldots,c_n,h_1,\ldots,h_m,\oplus,\otimes,\circledast)$, kde~$X$ je množina +vÅ¡ech ohodnocení sledů, {\bf 0}, $c_1,\ldots,c_n$ a $h_1,\ldots,h_m$ jsou konstanty, +$\oplus$ a~$\otimes$ binární operace a $\circledast$ unární operace. Průběh výpočtu +upraveného algoritmu je pak homomorfním obrazem průběhu výpočtu původního algoritmu +pracujícího přímo se svazky. -\s{Pøíklady:} +\s{Příklady:} -\>{\I Nejkrat¹í sled:} +\>{\I Nejkratší sled:} $$\eqalign{ f(\emptyset)&=+\infty \cr f(\varepsilon)&=0 \cr -f(e)&=\ell(e) \hbox{\quad (délka hrany~$e$)} \cr +f(e)&=\ell(e) \hbox{\quad (délka hrany~$e$)} \cr f(\alpha\cup\beta) &= \min(f(\alpha),f(\beta)) \cr f(\alpha\beta) &= f(\alpha) + f(\beta) \cr f(\alpha^*) &= \cases{0 & \hbox{pro $f(\alpha)\ge 0$} \cr -\infty & \hbox{pro $f(\alpha)<0$} \cr} \cr }$$ -(Pokud pøedpokládáme, ¾e v~grafu nejsou záporné cykly, je $f(\alpha^*)$ v¾dy nulové -a dostaneme pøesnì Floydùv-Warshallùv algoritmus.) +(Pokud předpokládáme, že v~grafu nejsou záporné cykly, je $f(\alpha^*)$ vždy nulové +a dostaneme přesně Floydův-Warshallův algoritmus.) -\>{\I Nej¹ir¹í cesta} (hranám jsou pøiøazeny ¹íøky, ¹íøka cesty je minimum z~¹íøek hran): +\>{\I NejÅ¡irší cesta} (hranám jsou přiřazeny šířky, šířka cesty je minimum z~šířek hran): $$\eqalign{ f(\emptyset)&=0 \cr f(\varepsilon)&=\infty \cr -f(e)&=w(e) \hbox{\quad (¹íøka hrany~$e$)} \cr +f(e)&=w(e) \hbox{\quad (šířka hrany~$e$)} \cr f(\alpha\cup\beta) &= \max(f(\alpha),f(\beta)) \cr f(\alpha\beta) &= \min(f(\alpha),f(\beta)) \cr f(\alpha^*) &= \infty \cr }$$ -\>{\I Pøevod koneèného automatu na regulární výraz:} Vrcholy multigrafu budou odpovídat -stavùm automatu, hrany mo¾ným pøechodùm mezi stavy. Ka¾dou hranu ohodnotíme symbolem -abecedy, po jeho¾ pøeètení automat pøechod provede. Funkce~$f$ pak pøiøadí $uv$-svazku~$\psi$ -regulární výraz popisující mno¾inu v¹ech øetìzcù, po jejich¾ pøeètení automat pøejde -ze~stavu~$u$ do stavu~$v$ po pøechodech z~mno¾iny~$\psi$. Vyhodnocování funkce~$f$ -odpovídá pøímoèarým operacím s~øetìzci. +\>{\I Převod konečného automatu na regulární výraz:} Vrcholy multigrafu budou odpovídat +stavům automatu, hrany možným přechodům mezi stavy. Každou hranu ohodnotíme symbolem +abecedy, po jehož přečtení automat přechod provede. Funkce~$f$ pak přiřadí $uv$-svazku~$\psi$ +regulární výraz popisující množinu vÅ¡ech řetězců, po jejichž přečtení automat přejde +ze~stavu~$u$ do stavu~$v$ po přechodech z~množiny~$\psi$. Vyhodnocování funkce~$f$ +odpovídá přímočarým operacím s~řetězci. -\h{Násobení matic} +\h{Násobení matic} -Øe¹íme-li grafové problémy pomocí matic, nabízí se pou¾ít známé subkubické algoritmy -pro lineárnì algebraické úlohy. Ty jsou obvykle zalo¾eny na efektivním násobení -matic -- dvì matice $n\times n$ mù¾eme vynásobit v~èase: +Řešíme-li grafové problémy pomocí matic, nabízí se použít známé subkubické algoritmy +pro lineárně algebraické úlohy. Ty jsou obvykle založeny na efektivním násobení +matic -- dvě matice $n\times n$ můžeme vynásobit v~čase: \itemize\ibull \:$\O(n^3)$ podle definice, -\:$\O(n^{2.808})$ Strassenovým algoritmem~\cite{strassen:matmult}, +\:$\O(n^{2.808})$ Strassenovým algoritmem~\cite{strassen:matmult}, \:$\O(n^{2.376})$ algoritmem Coppersmithe a Winograda~\cite{coppersmith:matmult}, -\:$\O(n^{2.373})$ algoritmem Williamsové~\cite{williams:matmult}. +\:$\O(n^{2.373})$ algoritmem Williamsové~\cite{williams:matmult}. \endlist -Obecnì pøijímaná hypotéza øíká, ¾e pro ka¾dé $\omega>2$ existuje algoritmus -násobící matice se slo¾itostí $\O(n^\omega)$. Jediný známý dolní odhad je pøitom -$\Omega(n^2\log n)$ pro aritmetické obvody s~omezenou velikostí konstant~\cite{raz:mmlower}. -Blí¾e se o~tomto fascinujícím tématu mù¾ete doèíst v~Szegedyho èlánku \cite{szegedy:matmult}. +Obecně přijímaná hypotéza říká, že pro každé $\omega>2$ existuje algoritmus +násobící matice se složitostí $\O(n^\omega)$. Jediný známý dolní odhad je přitom +$\Omega(n^2\log n)$ pro aritmetické obvody s~omezenou velikostí konstant~\cite{raz:mmlower}. +Blíže se o~tomto fascinujícím tématu můžete dočíst v~Szegedyho článku \cite{szegedy:matmult}. -Pøedpokládejme tedy, ¾e umíme násobit matice v~èase $\O(n^\omega)$ pro nìjaké $\omega < 3$. +Předpokládejme tedy, že umíme násobit matice v~čase $\O(n^\omega)$ pro nějaké $\omega < 3$. -Co se stane, kdy¾ mocníme matici sousednosti~$A$ grafu? V~matici $A^k$ se na pozici -$i,j$ nachází poèet sledù délky~$k$, které vedou z~vrcholu~$i$ do vrcholu~$j$. -(Snadný dùkaz indukcí vynecháváme.) Pro libovolné $k\ge n-1$ jsou tedy v~$(A+E)^k$ -(kde $E$ znaèí jednotkovou matici; doplnili jsme tedy do grafu smyèky) nenuly -pøesnì tam, kde z~$i$ do~$j$ vede cesta. +Co se stane, když mocníme matici sousednosti~$A$ grafu? V~matici $A^k$ se na pozici +$i,j$ nachází počet sledů délky~$k$, které vedou z~vrcholu~$i$ do vrcholu~$j$. +(Snadný důkaz indukcí vynecháváme.) Pro libovolné $k\ge n-1$ jsou tedy v~$(A+E)^k$ +(kde $E$ značí jednotkovou matici; doplnili jsme tedy do grafu smyčky) nenuly +přesně tam, kde z~$i$ do~$j$ vede cesta. -To nám dává jednoduchý algoritmus pro výpoèet matice dosa¾itelnosti~$R$ ($R_{ij}$ -je 1 nebo~0 podle toho, zda z~$i$ do~$j$ vede cesta). Do~matice~$A$ doplníme -na diagonálu jednièky a poté ji $\lceil \log_2 n\rceil$-krát umocníme na~druhou. -Abychom se vyhnuli velkým èíslùm, nahradíme po ka¾dém umocnìní nenuly jednièkami. -Celkem tedy provedeme $\O(\log n)$ násobení matic, co¾ trvá $\O(n^\omega\log n)$. +To nám dává jednoduchý algoritmus pro výpočet matice dosažitelnosti~$R$ ($R_{ij}$ +je 1 nebo~0 podle toho, zda z~$i$ do~$j$ vede cesta). Do~matice~$A$ doplníme +na diagonálu jedničky a poté ji $\lceil \log_2 n\rceil$-krát umocníme na~druhou. +Abychom se vyhnuli velkým číslům, nahradíme po každém umocnění nenuly jedničkami. +Celkem tedy provedeme $\O(\log n)$ násobení matic, což trvá $\O(n^\omega\log n)$. -Na~tento postup se mù¾eme dívat i~obecnìji: +Na~tento postup se můžeme dívat i~obecněji: -\s{Definice:} {\I $(\oplus,\otimes)$-souèin} matic~$A,B \in X^{n\times n}$, -kde $\oplus$ a~$\otimes$ jsou dvì asociativní binární operace na~mno¾inì~$X$, -je matice~$C$ taková, ¾e +\s{Definice:} {\I $(\oplus,\otimes)$-součin} matic~$A,B \in X^{n\times n}$, +kde $\oplus$ a~$\otimes$ jsou dvě asociativní binární operace na~množině~$X$, +je matice~$C$ taková, že $$ C_{ij} = \bigoplus_{k=1}^n A_{ik}\otimes B_{kj}. $$ -Klasické násobení matic je tedy $(+,\cdot)$-souèin. - -\s{Pozorování:} Pokud $A$ a~$B$ jsou matice svazkù ($A_{ij}$ a $B_{ij}$ -jsou $ij$-svazky) a $C$ jejich $(\cup,\cdot)$-souèin, pak $C_{ij}$ je -svazek v¹ech sledù vzniklých spojením nìjakého sledu z~$A$ zaèínajícího -v~$i$ a nìjakého sledu z~$B$ konèícího v~$j$. - -Podobnì jako v~pøedchozí sekci si tedy mù¾eme poøídit funkci~$f$ pøiøazující -svazkùm hodnoty z~nìjaké mno¾iny~$X$ a operace $\oplus$ a $\otimes$ na~$X$, -pro nì¾ platí $f(\alpha\cup\beta) = f(\alpha) \oplus f(\beta)$ a $f(\alpha\beta) -= f(\alpha) \otimes f(\beta)$. Pak staèí vzít matici popisující ohodnocení -v¹ech sledù délky 0 nebo~1 (to je obdoba matice sousednosti), a provést $\O(\log n)$ -$(\oplus,\otimes)$-souèinù k~tomu, abychom znali ohodnocení svazkù sledù délky -právì~$k$ pro nìjaké $k\ge n$. - -S~$(\lor,\land)$-souèiny a maticí sousednosti s~jednièkami na diagonále získáme -algoritmus pro výpoèet dosa¾itelnosti. Ka¾dý souèin pøitom mù¾eme provést jako -obyèejné násobení matic následované pøepsáním nenul na jednièky, tak¾e celý -výpoèet bì¾í v~èase $\O(n^\omega\log n)$. - -Podobnì mù¾eme poèítat i matici vzdáleností: zaèneme s~maticí délek hran doplnìnou o~nuly na~diagonále -a pou¾ijeme $(\min,+)$-souèiny. Tyto souèiny ale bohu¾el neumíme pøevést na klasické násobení matic. -Pøesto je známo nìkolik algoritmù efektivnìj¹ích ne¾ $\Theta(n^3)$, by» pouze o~málo: -napøíklad Zwickùv \cite{zwick:apsp} v~èase $\O(n^3\sqrt{\log\log n}/\log n)$ -(zalo¾ený na dekompozici a pøedpoèítání malých blokù) nebo Chanùv \cite{chan:apsp} v~$\O(n^3/\log n)$ -(pou¾ívající geometrické techniky). Abychom porazili Floydùv-Warshallùv algoritmus, -potøebovali bychom ov¹em vìt¹í ne¾ logaritmické zrychlení, proto¾e souèinù potøebujeme -vypoèítat logaritmicky mnoho. - -Dodejme je¹tì, ¾e pro grafy ohodnocené malými celými èísly je mo¾né vyu¾ít -celou øadu dal¹ích trikù. Zájemce o~tento druh algoritmù odkazujeme na Zwickùv -èlánek~\cite{zwick:apspint}. - -\h{Rozdìl a panuj} - -Pøedchozí pøevod je ov¹em trochu marnotratný. ©ikovným pou¾itím metody Rozdìl a panuj -mù¾eme èasovou slo¾itost je¹tì sní¾it. Postup pøedvedeme pro dosa¾itelnost: na vstupu -tedy dostaneme matici sousednosti~$A$, výstupem má být její transitivní uzávìr~$A^*$ -(matice dosa¾itelnosti). V¹echny souèiny matic v~tomto oddílu budou typu $(\lor,\land)$. - -Vrcholy grafu rozdìlíme na dvì mno¾iny $X$ a~$Y$ pøibli¾nì stejné velikosti, -bez újmy na obecnosti tak, aby matice~$A$ mìla následující blokový tvar: +Klasické násobení matic je tedy $(+,\cdot)$-součin. + +\s{Pozorování:} Pokud $A$ a~$B$ jsou matice svazků ($A_{ij}$ a $B_{ij}$ +jsou $ij$-svazky) a $C$ jejich $(\cup,\cdot)$-součin, pak $C_{ij}$ je +svazek vÅ¡ech sledů vzniklých spojením nějakého sledu z~$A$ začínajícího +v~$i$ a nějakého sledu z~$B$ končícího v~$j$. + +Podobně jako v~předchozí sekci si tedy můžeme pořídit funkci~$f$ přiřazující +svazkům hodnoty z~nějaké množiny~$X$ a operace $\oplus$ a $\otimes$ na~$X$, +pro něž platí $f(\alpha\cup\beta) = f(\alpha) \oplus f(\beta)$ a $f(\alpha\beta) += f(\alpha) \otimes f(\beta)$. Pak stačí vzít matici popisující ohodnocení +vÅ¡ech sledů délky 0 nebo~1 (to je obdoba matice sousednosti), a provést $\O(\log n)$ +$(\oplus,\otimes)$-součinů k~tomu, abychom znali ohodnocení svazků sledů délky +právě~$k$ pro nějaké $k\ge n$. + +S~$(\lor,\land)$-součiny a maticí sousednosti s~jedničkami na diagonále získáme +algoritmus pro výpočet dosažitelnosti. Každý součin přitom můžeme provést jako +obyčejné násobení matic následované přepsáním nenul na jedničky, takže celý +výpočet běží v~čase $\O(n^\omega\log n)$. + +Podobně můžeme počítat i matici vzdáleností: začneme s~maticí délek hran doplněnou o~nuly na~diagonále +a použijeme $(\min,+)$-součiny. Tyto součiny ale bohužel neumíme převést na klasické násobení matic. +Přesto je známo několik algoritmů efektivnějších než $\Theta(n^3)$, byÅ¥ pouze o~málo: +například Zwickův \cite{zwick:apsp} v~čase $\O(n^3\sqrt{\log\log n}/\log n)$ +(založený na dekompozici a předpočítání malých bloků) nebo Chanův \cite{chan:apsp} v~$\O(n^3/\log n)$ +(používající geometrické techniky). Abychom porazili Floydův-Warshallův algoritmus, +potřebovali bychom ovÅ¡em větší než logaritmické zrychlení, protože součinů potřebujeme +vypočítat logaritmicky mnoho. + +Dodejme jeÅ¡tě, že pro grafy ohodnocené malými celými čísly je možné využít +celou řadu dalších triků. Zájemce o~tento druh algoritmů odkazujeme na Zwickův +článek~\cite{zwick:apspint}. + +\h{Rozděl a panuj} + +Předchozí převod je ovÅ¡em trochu marnotratný. Å ikovným použitím metody Rozděl a panuj +můžeme časovou složitost jeÅ¡tě snížit. Postup předvedeme pro dosažitelnost: na vstupu +tedy dostaneme matici sousednosti~$A$, výstupem má být její transitivní uzávěr~$A^*$ +(matice dosažitelnosti). VÅ¡echny součiny matic v~tomto oddílu budou typu $(\lor,\land)$. + +Vrcholy grafu rozdělíme na dvě množiny $X$ a~$Y$ přibližně stejné velikosti, +bez újmy na obecnosti tak, aby matice~$A$ měla následující blokový tvar: $$A = \pmatrix{ P & Q \cr R & S \cr },$$ kde podmatice~$P$ popisuje hrany z~$X$ do~$X$, podmatice~$Q$ hrany z~$X$ do~$Y$, atd. -\s{Vìta:} Pokud matici~$A^*$ zapí¹eme rovnì¾ v~blokovém tvaru: +\s{Věta:} Pokud matici~$A^*$ zapíšeme rovněž v~blokovém tvaru: $$A^* = \pmatrix{ I & J \cr K & L \cr },$$ bude platit: $$\eqalign{ @@ -278,84 +278,84 @@ L &= S^* \lor S^*RIQS^*. }$$ \proof -Jednotlivé rovnosti mù¾eme èíst takto: +Jednotlivé rovnosti můžeme číst takto: \def\nIJKL{\count0=`H\advance\count0 by\itemcount{\bf\char\count0:}} \numlist\nIJKL -\:Sled z~$X$ do~$X$ vznikne opakováním èástí, z~nich¾ ka¾dá je buïto -hrana uvnitø~$X$ nebo pøechod po hranì z~$X$ do~$Y$ následovaný sledem -uvnitø~$Y$ a pøechodem zpìt do~$X$. -\:Sled z~$X$ do~$Y$ mù¾eme rozdìlit v~místì, kdy naposledy pøechází -po~hranì z~$X$ do~$Y$. První èást pøitom bude sled z~$X$ do~$X$, -druhá sled uvnitø~$Y$. -\:Se sledem z~$Y$ do~$X$ nalo¾íme symetricky. -\:Sled z~$Y$ do~$Y$ vede buïto celý uvnitø~$Y$, nebo ho mù¾eme rozdìlit -na~prvním pøechodu z~$Y$ do~$X$ a posledním pøechodu z~$X$ do~$Y$. -Èást pøed prvním pøechodem povede celá uvnitø~$Y$, èást mezi pøechody -bude tvoøit sled z~$X$ do~$X$ a koneènì èást za~posledním pøechodem zùstane -opìt uvnitø~$Y$. +\:Sled z~$X$ do~$X$ vznikne opakováním částí, z~nichž každá je buďto +hrana uvnitř~$X$ nebo přechod po hraně z~$X$ do~$Y$ následovaný sledem +uvnitř~$Y$ a přechodem zpět do~$X$. +\:Sled z~$X$ do~$Y$ můžeme rozdělit v~místě, kdy naposledy přechází +po~hraně z~$X$ do~$Y$. První část přitom bude sled z~$X$ do~$X$, +druhá sled uvnitř~$Y$. +\:Se sledem z~$Y$ do~$X$ naložíme symetricky. +\:Sled z~$Y$ do~$Y$ vede buďto celý uvnitř~$Y$, nebo ho můžeme rozdělit +na~prvním přechodu z~$Y$ do~$X$ a posledním přechodu z~$X$ do~$Y$. +Část před prvním přechodem povede celá uvnitř~$Y$, část mezi přechody +bude tvořit sled z~$X$ do~$X$ a konečně část za~posledním přechodem zůstane +opět uvnitř~$Y$. \qeditem \endlist \s{Algoritmus:} -Výpoèet matice~$A^*$ provedeme podle pøedchozí vìty. Spoèítáme 2~tranzitivní uzávìry -matic polovièní velikosti rekurzivním voláním, dále pak $\O(1)$ $(\lor,\land)$-souèinù -a $\O(1)$ souètù matic. +Výpočet matice~$A^*$ provedeme podle předchozí věty. Spočítáme 2~tranzitivní uzávěry +matic poloviční velikosti rekurzivním voláním, dále pak $\O(1)$ $(\lor,\land)$-součinů +a $\O(1)$ součtů matic. -Èasová slo¾itost $t(n)$ tohoto algoritmu bude splòovat následující rekurenci: +Časová složitost $t(n)$ tohoto algoritmu bude splňovat následující rekurenci: $$t(1)=\Theta(1), \quad t(n) = 2t(n/2) + \Theta(1)\cdot\mu(n/2) + \Theta(n^2),$$ -kde $\mu(k)$ znaèí èas potøebný na jeden $(\lor,\land)$-souèin -matic $k\times k$. Jeliko¾ jistì platí $\mu(n/2)=\Omega(n^2)$, -má tato rekurence podle kuchaøkové vìty øe¹ení $t(n) = \mu(n)$. - -Ukázali jsme tedy, ¾e výpoèet matice dosa¾itelnosti je nejvý¹e stejnì -nároèný jako $(\lor,\land)$-násobení matic -- mù¾eme ho proto provést -v~èase $\O(n^\omega)$. Dokonce existuje pøímoèarý pøevod v~opaèném smìru, -tak¾e oba problémy jsou asymptoticky stejnì tì¾ké. - -Podobnì nalézt matici vzdáleností je stejnì tì¾ké jako $(\min,+)$-souèin, -tak¾e na to staèí èas $\O(n^3/\log n)$. - -\h{Seidelùv algoritmus} - -Pro neorientované neohodnocené grafy mù¾eme dosáhnout je¹tì lep¹ích -výsledkù. Matici vzdáleností lze spoèítat v~èase $\O(n^\omega\log n)$ -Seidelovým algoritmem~\cite{seidel:unitlength}. Ten funguje následovnì: - -\s{Definice:} {\I Druhá mocnina grafu~$G$} je graf~$G^2$ na té¾e mno¾inì vrcholù, -v~nìm¾ jsou vrcholy~$i$ a~$j$ spojeny hranou právì tehdy, existuje-li v~$G$ sled -délky nejvý¹e~2 vedoucí z~$i$ do~$j$. - -\s{Pozorování:} Matici sousednosti grafu~$G^2$ získáme z~matice sousednosti -grafu~$G$ jedním $(\lor,\land)$-souèinem, tedy v~èase $\O(n^\omega)$. - -Seidelùv algoritmus bude postupovat rekurzivnì: Sestrojí graf~$G^2$, rekurzí -spoèítá jeho matici vzdáleností~$D'$ a z~ní pak rekonstruuje matici vzdáleností~$D$ -zadaného grafu. Rekurze konèí, pokud $G^2=G$ -- tehdy je ka¾dá komponenta -souvislosti zahu¹tìna na~úplný graf, tak¾e matice vzdáleností je rovna matici sousednosti. - -Zbývá ukázat, jak z~matice~$D'$ spoèítat matici~$D$. Zvolme pevnì~$i$ a zamìøme -se na funkce $d(v)=D_{iv}$ a $d'(v)=D'_{iv}$. Jistì platí $d'(v) = \lceil d(v)/2 \rceil$, -proèe¾ $d(v)$ je buï rovno $2d'(v)$ nebo o~1 ni¾¹í. Nauèíme se rozpoznat, jestli -$d(v)$ má být sudé nebo liché, a~z~toho v¾dy poznáme, jestli je potøeba jednièku odeèíst. - -Jak vypadá funkce~$d$ na sousedech vrcholu~$v\ne i$? Pro alespoò jednoho souseda~$u$ je -$d(u) = d(v)-1$ (to platí pro sousedy, kteøí le¾í na nìkteré z~nejkrat¹ích cest z~$v$ do~$i$). -Pro v¹echny ostatní sousedy je $d(u)=d(v)$ nebo $d(u)=d(v)+1$. - -Pokud je $d(v)$ sudé, vyjde pro sousedy le¾ící na nejkrat¹ích cestách $d'(u)=d'(v)$ -a pro ostatní sousedy $d'(u)\ge d'(v)$, tak¾e prùmìr z~$d'(u)$ pøes sousedy je -alespoò~$d'(v)$. Je-li naopak $d(v)$ liché, musí být pro sousedy na nejkrat¹ích cestách -$d'(u) < d(v)$ a pro v¹echny ostatní $d'(u) = d(v)$, tak¾e prùmìr klesne pod~$d'(v)$. - -Prùmìry pøes sousedy pøitom mù¾eme spoèítat násobením matic: vynásobíme matici -vzdáleností~$D'$ maticí sousednosti grafu~$G$. Na pozici~$i,j$ se objeví souèet -hodnot $D'_{ik}$ pøes v¹echny sousedy~$k$ vrcholu~$j$. Ten staèí vydìlit stupnìm -vrcholu~$j$ a hledaný prùmìr je na svìtì. - -Po~provedení jednoho násobení matic tedy dovedeme pro ka¾dou dvojici vrcholù -v~konstantním èase spoèítat $D_{ij}$ z~$D'_{ij}$. Jedna úroveò rekurze proto -trvá $\O(n^\omega)$ a jeliko¾ prùmìr grafu poka¾dé klesne alespoò dvakrát, -je úrovní $\O(\log n)$ a celý algoritmus dobìhne ve~slíbeném èase $\O(n^\omega\log n)$. +kde $\mu(k)$ značí čas potřebný na jeden $(\lor,\land)$-součin +matic $k\times k$. Jelikož jistě platí $\mu(n/2)=\Omega(n^2)$, +má tato rekurence podle kuchařkové věty řeÅ¡ení $t(n) = \mu(n)$. + +Ukázali jsme tedy, že výpočet matice dosažitelnosti je nejvýše stejně +náročný jako $(\lor,\land)$-násobení matic -- můžeme ho proto provést +v~čase $\O(n^\omega)$. Dokonce existuje přímočarý převod v~opačném směru, +takže oba problémy jsou asymptoticky stejně těžké. + +Podobně nalézt matici vzdáleností je stejně těžké jako $(\min,+)$-součin, +takže na to stačí čas $\O(n^3/\log n)$. + +\h{Seidelův algoritmus} + +Pro neorientované neohodnocené grafy můžeme dosáhnout jeÅ¡tě lepších +výsledků. Matici vzdáleností lze spočítat v~čase $\O(n^\omega\log n)$ +Seidelovým algoritmem~\cite{seidel:unitlength}. Ten funguje následovně: + +\s{Definice:} {\I Druhá mocnina grafu~$G$} je graf~$G^2$ na téže množině vrcholů, +v~němž jsou vrcholy~$i$ a~$j$ spojeny hranou právě tehdy, existuje-li v~$G$ sled +délky nejvýše~2 vedoucí z~$i$ do~$j$. + +\s{Pozorování:} Matici sousednosti grafu~$G^2$ získáme z~matice sousednosti +grafu~$G$ jedním $(\lor,\land)$-součinem, tedy v~čase $\O(n^\omega)$. + +Seidelův algoritmus bude postupovat rekurzivně: Sestrojí graf~$G^2$, rekurzí +spočítá jeho matici vzdáleností~$D'$ a z~ní pak rekonstruuje matici vzdáleností~$D$ +zadaného grafu. Rekurze končí, pokud $G^2=G$ -- tehdy je každá komponenta +souvislosti zahuÅ¡těna na~úplný graf, takže matice vzdáleností je rovna matici sousednosti. + +Zbývá ukázat, jak z~matice~$D'$ spočítat matici~$D$. Zvolme pevně~$i$ a zaměřme +se na funkce $d(v)=D_{iv}$ a $d'(v)=D'_{iv}$. Jistě platí $d'(v) = \lceil d(v)/2 \rceil$, +pročež $d(v)$ je buď rovno $2d'(v)$ nebo o~1 nižší. Naučíme se rozpoznat, jestli +$d(v)$ má být sudé nebo liché, a~z~toho vždy poznáme, jestli je potřeba jedničku odečíst. + +Jak vypadá funkce~$d$ na sousedech vrcholu~$v\ne i$? Pro alespoň jednoho souseda~$u$ je +$d(u) = d(v)-1$ (to platí pro sousedy, kteří leží na některé z~nejkratších cest z~$v$ do~$i$). +Pro vÅ¡echny ostatní sousedy je $d(u)=d(v)$ nebo $d(u)=d(v)+1$. + +Pokud je $d(v)$ sudé, vyjde pro sousedy ležící na nejkratších cestách $d'(u)=d'(v)$ +a pro ostatní sousedy $d'(u)\ge d'(v)$, takže průměr z~$d'(u)$ přes sousedy je +alespoň~$d'(v)$. Je-li naopak $d(v)$ liché, musí být pro sousedy na nejkratších cestách +$d'(u) < d(v)$ a pro vÅ¡echny ostatní $d'(u) = d(v)$, takže průměr klesne pod~$d'(v)$. + +Průměry přes sousedy přitom můžeme spočítat násobením matic: vynásobíme matici +vzdáleností~$D'$ maticí sousednosti grafu~$G$. Na pozici~$i,j$ se objeví součet +hodnot $D'_{ik}$ přes vÅ¡echny sousedy~$k$ vrcholu~$j$. Ten stačí vydělit stupněm +vrcholu~$j$ a hledaný průměr je na světě. + +Po~provedení jednoho násobení matic tedy dovedeme pro každou dvojici vrcholů +v~konstantním čase spočítat $D_{ij}$ z~$D'_{ij}$. Jedna úroveň rekurze proto +trvá $\O(n^\omega)$ a jelikož průměr grafu pokaždé klesne alespoň dvakrát, +je úrovní $\O(\log n)$ a celý algoritmus doběhne ve~slíbeném čase $\O(n^\omega\log n)$. \references \bye diff --git a/2-dinic/2-dinic.tex b/2-dinic/2-dinic.tex index e3f36ae..86c7236 100644 --- a/2-dinic/2-dinic.tex +++ b/2-dinic/2-dinic.tex @@ -1,358 +1,358 @@ \input ../sgr.tex -\prednaska{2}{Dinicùv algoritmus a jeho varianty}{} +\prednaska{2}{Dinicův algoritmus a jeho varianty}{} -Maximální tok v~síti u¾ umíme najít pomocí Fordova-Fulkersonova algoritmu -z~minulé kapitoly. Nyní pojednáme o~efektivnìj¹ím Dinicovì algoritmu -a o~rùzných jeho variantách pro sítì ve~speciálním tvaru. +Maximální tok v~síti už umíme najít pomocí Fordova-Fulkersonova algoritmu +z~minulé kapitoly. Nyní pojednáme o~efektivnějším Dinicově algoritmu +a o~různých jeho variantách pro sítě ve~speciálním tvaru. -\h{Dinicùv algoritmus} +\h{Dinicův algoritmus} -Dinicùv algoritmus je zalo¾en na~následující my¹lence: Ve~Fordovì-Fulkersonovì algoritmu -nemusíme pøièítat jen zlep¹ující cesty, ale je mo¾né pøièítat rovnou zlep¹ující -toky. Nejlépe toky takové, aby je nebylo obtí¾né najít, a~pøitom aby pùvodní tok -dostateènì obohatily. Vhodnými objekty k~tomuto úèelu jsou blokující toky: +Dinicův algoritmus je založen na~následující myÅ¡lence: Ve~Fordově-Fulkersonově algoritmu +nemusíme přičítat jen zlepÅ¡ující cesty, ale je možné přičítat rovnou zlepÅ¡ující +toky. Nejlépe toky takové, aby je nebylo obtížné najít, a~přitom aby původní tok +dostatečně obohatily. Vhodnými objekty k~tomuto účelu jsou blokující toky: -\s{Definice:} {\I Blokující tok} je tok takový, ¾e ka¾dá orientovaná $st$-cesta -obsahuje alespoò jednu nasycenou hranu. [Tj. takový tok, který by na¹el F-F algoritmus, -kdyby neuva¾oval rezervy v~protismìru.] +\s{Definice:} {\I Blokující tok} je tok takový, že každá orientovaná $st$-cesta +obsahuje alespoň jednu nasycenou hranu. [Tj. takový tok, který by naÅ¡el F-F algoritmus, +kdyby neuvažoval rezervy v~protisměru.] \s{Algoritmus (Dinic):} \algo -\:Zaèneme s~libovolným tokem~$f$, napøíklad prázdným (v¹ude nulovým). -\:Iterativnì vylep¹ujeme tok pomocí zlep¹ujících tokù: {\I (vnìj¹í cyklus)} -\::Sestrojíme sí» rezerv: vrcholy a hrany jsou tyté¾, kapacity jsou urèeny rezervami v~pùvodní síti. -Dále budeme pracovat s~ní. -\::Najdeme nejkrat¹í $st$-cestu. Kdy¾ ¾ádná neexistuje, skonèíme. -\::Proèistíme sí», tj. ponecháme v ní pouze vrcholy a hrany na nejkrat¹ích $st$-cestách. -\::Najdeme v~proèi¹tìné síti blokující tok $f_B$: -\:::$f_B \leftarrow \$ -\:::Postupnì pøidáváme $st$-cesty: {\I (vnitøní cyklus)} -\::::Najdeme $st$-cestu. Napø. hladovì -- \uv{rovnou za nosem}. -\::::Po¹leme co nejvíce po~nalezené cestì. -\::::Sma¾eme nasycené hrany. (Pozor, smazáním hran mohou vzniknout slepé ulièky, -èím¾ se zneèistí sí» a nebude fungovat hladové hledání cest.) -\::::Doèistíme sí». -\::Zlep¹íme $f$ podle $f_B$ +\:Začneme s~libovolným tokem~$f$, například prázdným (vÅ¡ude nulovým). +\:Iterativně vylepÅ¡ujeme tok pomocí zlepÅ¡ujících toků: {\I (vnější cyklus)} +\::Sestrojíme síť rezerv: vrcholy a hrany jsou tytéž, kapacity jsou určeny rezervami v~původní síti. +Dále budeme pracovat s~ní. +\::Najdeme nejkratší $st$-cestu. Když žádná neexistuje, skončíme. +\::Pročistíme síť, tj. ponecháme v ní pouze vrcholy a hrany na nejkratších $st$-cestách. +\::Najdeme v~pročiÅ¡těné síti blokující tok $f_B$: +\:::$f_B \leftarrow \$ +\:::Postupně přidáváme $st$-cesty: {\I (vnitřní cyklus)} +\::::Najdeme $st$-cestu. Např. hladově -- \uv{rovnou za nosem}. +\::::PoÅ¡leme co nejvíce po~nalezené cestě. +\::::Smažeme nasycené hrany. (Pozor, smazáním hran mohou vzniknout slepé uličky, +čímž se znečistí síť a nebude fungovat hladové hledání cest.) +\::::Dočistíme síť. +\::Zlepšíme $f$ podle $f_B$ \endalgo \finalfix{\vskip-3pt} -\figure{dinic-cistasit.eps}{Proèi¹tìná sí» rozdìlená do vrstev}{0.4\hsize} +\figure{dinic-cistasit.eps}{PročiÅ¡těná síť rozdělená do vrstev}{0.4\hsize} \finalfix{\vskip-6pt} -\s{Slo¾itost algoritmu:} -Oznaème $l$ délku nejkrat¹í $st$-cesty, $n$ poèet vrcholù sítì a $m$ poèet hran sítì. +\s{Složitost algoritmu:} +Označme $l$ délku nejkratší $st$-cesty, $n$ počet vrcholů sítě a $m$ počet hran sítě. \itemize\ibull -\:Jeden prùchod vnitøním cyklem trvá $\O(l)$, co¾ mù¾eme odhadnout jako $\O(n)$, proto¾e v¾dy platí $l \leq n$. -\:Vnitøní cyklus se provede maximálnì $m$-krát, proto¾e se v¾dy alespoò jedna hrana nasytí - a ze sítì vypadne, tak¾e krok~6 mimo podkroku~12 bude trvat $\O(mn)$. -\:Èi¹tìní a doèi¹»ování sítì dohromady provedeme takto: +\:Jeden průchod vnitřním cyklem trvá $\O(l)$, což můžeme odhadnout jako $\O(n)$, protože vždy platí $l \leq n$. +\:Vnitřní cyklus se provede maximálně $m$-krát, protože se vždy alespoň jedna hrana nasytí + a ze sítě vypadne, takže krok~6 mimo podkroku~12 bude trvat $\O(mn)$. +\:ČiÅ¡tění a dočiÅ¡Å¥ování sítě dohromady provedeme takto: \itemize\ibull - \:Rozvrstvíme vrcholy podle vzdálenosti od $s$. - \:Zaøízneme dlouhé cesty (del¹í, ne¾ do vrstvy obsahující $t$). - \:Dr¾íme si frontu vrcholù, které mají $\deg^+ = 0$ èi $\deg^- = 0$. - \:Vrcholy z~fronty vybíráme a zahazujeme vèetnì hran, které vedou do/z nich. - A pøípadnì pøidáváme do~fronty vrcholy, kterým pøi tom klesl jeden ze stupòù na 0. - Vyma¾ou se tím slepé ulièky, které by vadily v podkroku~9. + \:Rozvrstvíme vrcholy podle vzdálenosti od $s$. + \:Zařízneme dlouhé cesty (delší, než do vrstvy obsahující $t$). + \:Držíme si frontu vrcholů, které mají $\deg^+ = 0$ či $\deg^- = 0$. + \:Vrcholy z~fronty vybíráme a zahazujeme včetně hran, které vedou do/z nich. + A případně přidáváme do~fronty vrcholy, kterým při tom klesl jeden ze stupňů na 0. + Vymažou se tím slepé uličky, které by vadily v podkroku~9. \endlist - Takto kroky 5 a 12 dohromady spotøebují èas $\O(m)$. - \:Jeden prùchod vnìj¹ím cyklem tedy trvá $\O(mn)$. - \:Jak za chvíli doká¾eme, ka¾dým prùchodem vnìj¹ím cyklem $l$ vzroste, tak¾e prùchodù - bude maximálnì~$n$ a celý algoritmus tak pobì¾í v~èase $\O(n^2m)$. + Takto kroky 5 a 12 dohromady spotřebují čas $\O(m)$. + \:Jeden průchod vnějším cyklem tedy trvá $\O(mn)$. + \:Jak za chvíli dokážeme, každým průchodem vnějším cyklem $l$ vzroste, takže průchodů + bude maximálně~$n$ a celý algoritmus tak poběží v~čase $\O(n^2m)$. \endlist \s{Korektnost algoritmu:} -Kdy¾ se Dinicùv algoritmus zastaví, nemù¾e u¾ existovat ¾ádná zlep¹ující cesta -(viz krok~4) a tehdy, jak u¾ víme z~analýzy F-F algoritmu, je nalezený tok maximální. +Když se Dinicův algoritmus zastaví, nemůže už existovat žádná zlepÅ¡ující cesta +(viz krok~4) a tehdy, jak už víme z~analýzy F-F algoritmu, je nalezený tok maximální. -\s{Vìta:} -V~ka¾dém prùchodu Dinicova algoritmu vzroste $l$ alespoò~o~1. +\s{Věta:} +V~každém průchodu Dinicova algoritmu vzroste $l$ alespoň~o~1. \proof -Podíváme se na~prùbìh jednoho prùchodu vnìj¹ím cyklem. -Délku aktuálnì nejkrat¹í $st$-cesty oznaème~$l$. -V¹echny pùvodní cesty délky~$l$ se bìhem prùchodu zaruèenì nasytí, proto¾e -tok~$f_B$ je blokující. Musíme v¹ak dokázat, ¾e nemohou vzniknout ¾ádné -nové cesty délky~$l$ nebo men¹í. V~síti rezerv toti¾ mohou hrany nejen -ubývat, ale i pøibývat: pokud po¹leme tok po~hranì, po~které je¹tì nic -neteklo, tak v~protismìru z~dosud nulové rezervy vyrobíme nenulovou. -Rozmysleme si tedy, jaké hrany mohou pøibývat: - -Vnìj¹í cyklus zaèíná s neproèi¹tìnou sítí. Pøíklad takové sítì je na~následujícím obrázku. -Po~proèi¹tìní zùstanou v~síti jen èerné hrany, tedy hrany vedoucí z~$i$-té -vrstvy do~$(i+1)$-ní. Èervené a modré\foot{Modré jsou ty, které vedou v rámci jedné vrstvy, -èervené vedou zpìt èi za~spotøebiè èi do~slepých ulièek. Pøi vyti¹tìní na papír vypadají v¹echny èernì.} -se zahodí. - -Nové hrany mohou vznikat výhradnì jako opaèné k~èerným hranám (hrany ostatních barev -padly za obì» proèi¹tìní). Jsou to tedy v¾dy zpìtné hrany vedoucí z~$i$-té vrstvy do~$(i-1)$-ní. -Vznikem nových hran by proto mohly vzniknout nové $st$-cesty, které pou¾ívají -zpìtné hrany. Jen¾e $st$-cesta, která pou¾ije zpìtnou hranu, musí alespoò jednou skoèit -o~vrstvu zpìt a nikdy nemù¾e skoèit o~více ne¾ jednu vrstvu dopøedu, a~proto je její -délka alespoò $l+2$. Tím je vìta dokázána. \qed - -% posunut dále, aby vy¹la sazba -\figure{dinic-neprocistenasit.eps}{Neproèi¹tìná sí». Obsahuje zpìtné hrany, hrany uvnitø vrstvy a slepé ulièky.}{0.45\hsize} +Podíváme se na~průběh jednoho průchodu vnějším cyklem. +Délku aktuálně nejkratší $st$-cesty označme~$l$. +VÅ¡echny původní cesty délky~$l$ se během průchodu zaručeně nasytí, protože +tok~$f_B$ je blokující. Musíme vÅ¡ak dokázat, že nemohou vzniknout žádné +nové cesty délky~$l$ nebo menší. V~síti rezerv totiž mohou hrany nejen +ubývat, ale i přibývat: pokud poÅ¡leme tok po~hraně, po~které jeÅ¡tě nic +neteklo, tak v~protisměru z~dosud nulové rezervy vyrobíme nenulovou. +Rozmysleme si tedy, jaké hrany mohou přibývat: + +Vnější cyklus začíná s nepročiÅ¡těnou sítí. Příklad takové sítě je na~následujícím obrázku. +Po~pročiÅ¡tění zůstanou v~síti jen černé hrany, tedy hrany vedoucí z~$i$-té +vrstvy do~$(i+1)$-ní. Červené a modré\foot{Modré jsou ty, které vedou v rámci jedné vrstvy, +červené vedou zpět či za~spotřebič či do~slepých uliček. Při vytiÅ¡tění na papír vypadají vÅ¡echny černě.} +se zahodí. + +Nové hrany mohou vznikat výhradně jako opačné k~černým hranám (hrany ostatních barev +padly za oběť pročiÅ¡tění). Jsou to tedy vždy zpětné hrany vedoucí z~$i$-té vrstvy do~$(i-1)$-ní. +Vznikem nových hran by proto mohly vzniknout nové $st$-cesty, které používají +zpětné hrany. Jenže $st$-cesta, která použije zpětnou hranu, musí alespoň jednou skočit +o~vrstvu zpět a nikdy nemůže skočit o~více než jednu vrstvu dopředu, a~proto je její +délka alespoň $l+2$. Tím je věta dokázána. \qed + +% posunut dále, aby vyÅ¡la sazba +\figure{dinic-neprocistenasit.eps}{NepročiÅ¡těná síť. Obsahuje zpětné hrany, hrany uvnitř vrstvy a slepé uličky.}{0.45\hsize} % HACK \vskip -10pt -\figure{dinic-cestashranouzpet.eps}{Cesta u¾ívající novou zpìtnou hranu}{0.4\hsize} +\figure{dinic-cestashranouzpet.eps}{Cesta užívající novou zpětnou hranu}{0.4\hsize} -\h{Poznámky} +\h{Poznámky} \itemize\ibull -\:Není potøeba tak puntièkáøské èi¹tìní. Vrcholy se vstupním stupnìm 0 nám - nevadí -- stejnì se do nich nedostaneme. Vadí jen vrcholy s výstupním stupnìm 0, kde by mohl +\:Není potřeba tak puntičkářské čiÅ¡tění. Vrcholy se vstupním stupněm 0 nám + nevadí -- stejně se do nich nedostaneme. Vadí jen vrcholy s výstupním stupněm 0, kde by mohl havarovat postup v podkroku 9. -\:Je mo¾né dìlat prohledávání a èi¹tìní souèasnì. Jednodu¹e prohledáváním do~hloubky: - \uv{Hrrr na nì!} a kdy¾ - to nevyjde (dostaneme se do slepé ulièky), kus ustoupíme a pøi ústupu èistíme sí» - odstraòováním slepé ulièky. -\:U¾ pøi prohledávání si rovnou udr¾ujeme minimum z rezerv a pøi zpáteèní cestì - opravujeme kapacity. Snadno zkombinujeme s~prohledáváním do~hloubky. -\:V prùbìhu výpoètu udr¾ujeme jen sí» rezerv a tok vypoèteme a¾ nakonec z rezerv a kapacit. -\:Kdy¾ budeme chtít hledat minimální øez, spustíme po~Dinicovu algoritmu je¹tì jednu iterací F-F +\:Je možné dělat prohledávání a čiÅ¡tění současně. JednoduÅ¡e prohledáváním do~hloubky: + \uv{Hrrr na ně!} a když + to nevyjde (dostaneme se do slepé uličky), kus ustoupíme a při ústupu čistíme síť + odstraňováním slepé uličky. +\:Už při prohledávání si rovnou udržujeme minimum z rezerv a při zpáteční cestě + opravujeme kapacity. Snadno zkombinujeme s~prohledáváním do~hloubky. +\:V průběhu výpočtu udržujeme jen síť rezerv a tok vypočteme až nakonec z rezerv a kapacit. +\:Když budeme chtít hledat minimální řez, spustíme po~Dinicovu algoritmu jeÅ¡tě jednu iterací F-F algoritmu. \endlist -\h{Speciální sítì (ubíráme na obecnosti)} - -Pøi pøevodu rùzných úloh na~hledání maximálního toku èasto dostaneme sí» v~nìjakém -speciálním tvaru -- tøeba s~omezenými kapacitami èi stupni vrcholù. Podíváme se -proto podrobnìji na~chování Dinicova algoritmu v~takových pøípadech a uká¾eme, -¾e èasto pracuje pøekvapivì efektivnì. - -\s{Jednotkové kapacity:} -Pokud sí» neobsahuje cykly délky~2 (dvojice navzájem opaèných hran), v¹echny rezervy -jsou jen 0 nebo~1. Pokud obsahuje, mohou rezervy být i dvojky, a~proto sí» upravíme tak, -¾e ke~ka¾dé hranì pøidáme hranu opaènou s~nulovou kapacitou a rezervu proti smìru -toku pøiøkneme jí. Vzniknou tím sice paralelní hrany, ale to tokovým algoritmùm -nikterak nevadí.% -\foot{Èasto se to implementuje tak, ¾e protismìrné hrany vùbec nevytvoøíme a kdy¾ -hranu nasytíme, tak v~síti rezerv prostì obrátíme její orientaci.} - -Pøi hledání blokujícího toku tedy budou mít v¹echny hrany na~nalezené $st$-cestì -stejnou, toti¾ jednotkovou, rezervu, tak¾e v¾dy z~grafu odstraníme celou cestu. -Kdy¾ máme $m$ hran, poèet zlep¹ení po cestách délky $l$ bude maximálnì $m/l$. -Proto slo¾itost podkrokù 9, 10 a 11 bude $m/l \cdot \O(l) = \O(m)$.% -\foot{Nebo by ¹lo argumentovat, tím ¾e ka¾dou hranu pou¾ijeme jen $1\times$.} -Tedy pro jednotkové kapacity dostáváme slo¾itost $\O(nm)$. - -\s{Jednotkové kapacity znovu a lépe:} -Vnitøní cyklus lépe udìlat nepùjde. Je potøeba alespoò lineární èas pro èi¹tìní. -Mù¾eme se ale pokusit lépe odhadnout poèet iterací vnìj¹ího cyklu. - -Sledujme stav sítì po $k$ iteracích vnìj¹ího cyklu a pokusme se odhadnout, kolik iterací -je¹tì algoritmus udìlá. Oznaème~$l$ délku nejkrat¹í $st$-cesty. -Víme, ¾e $l>k$, proto¾e v ka¾dé iteraci vzroste $l$ alespoò o 1. - -Máme tok $f_k$ a chceme dostat maximální tok $f$. Rozdíl $f-f_k$ je tok v~síti rezerv -(tok v~pùvodní síti to ov¹em být nemusí!), oznaème si ho~$f_R$. -Ka¾dá iterace velkého cyklu zlep¹í $f_k$ alespoò o 1. Tedy nám zbývá je¹tì -nejvý¹e $\vert f_R \vert$ iterací. -Proto bychom chtìli omezit velikost toku $f_R$. Napøíklad øezem. - -Najdeme v síti rezerv nìjaký dost malý øez $C$. Kde ho vzít?\foot{Pøeci v øeznictví. Kdepak, spí¹e v cukrárnì. -Myslíte, ¾e v cukrárnì mají Dinicovy øezy? Myslím, ¾e v cukrárnì je vìt¹ina øezù minimální. {\sl (odposlechnuto na~pøedná¹ce)}} -Poèítejme jen hrany zleva doprava. Tìch je jistì nejvý¹e $m$ a tvoøí alespoò $k$ rozhraní mezi -vrstvami. Tedy existuje rozhraní vrstev -s~nejvý¹e $m/k$ hranami\foot{Princip holubníku a nìjaká ta $\pm1$.}. -Toto rozhraní je øez. Tedy existuje øez~$C$, pro nìj¾ $\vert C\vert \leq m/k$, -a~algoritmu zbývá maximálnì $m/k$ dal¹ích krokù. -Celkový poèet krokù je nejvý¹ $k + m/k$, tak¾e staèí zvolit $k = \sqrt{m}$ a získáme -odhad na~poèet krokù $\O(\sqrt{m})$. - -Tím jsme dokázali, ¾e celková slo¾itost Dinicova algoritmu pro jednotkové -kapacity je $\O(m^{3/2})$. Tím jsme si pomohli pro øídké grafy. +\h{Speciální sítě (ubíráme na obecnosti)} + +Při převodu různých úloh na~hledání maximálního toku často dostaneme síť v~nějakém +speciálním tvaru -- třeba s~omezenými kapacitami či stupni vrcholů. Podíváme se +proto podrobněji na~chování Dinicova algoritmu v~takových případech a ukážeme, +že často pracuje překvapivě efektivně. + +\s{Jednotkové kapacity:} +Pokud síť neobsahuje cykly délky~2 (dvojice navzájem opačných hran), vÅ¡echny rezervy +jsou jen 0 nebo~1. Pokud obsahuje, mohou rezervy být i dvojky, a~proto síť upravíme tak, +že ke~každé hraně přidáme hranu opačnou s~nulovou kapacitou a rezervu proti směru +toku přiřkneme jí. Vzniknou tím sice paralelní hrany, ale to tokovým algoritmům +nikterak nevadí.% +\foot{Často se to implementuje tak, že protisměrné hrany vůbec nevytvoříme a když +hranu nasytíme, tak v~síti rezerv prostě obrátíme její orientaci.} + +Při hledání blokujícího toku tedy budou mít vÅ¡echny hrany na~nalezené $st$-cestě +stejnou, totiž jednotkovou, rezervu, takže vždy z~grafu odstraníme celou cestu. +Když máme $m$ hran, počet zlepÅ¡ení po cestách délky $l$ bude maximálně $m/l$. +Proto složitost podkroků 9, 10 a 11 bude $m/l \cdot \O(l) = \O(m)$.% +\foot{Nebo by Å¡lo argumentovat, tím že každou hranu použijeme jen $1\times$.} +Tedy pro jednotkové kapacity dostáváme složitost $\O(nm)$. + +\s{Jednotkové kapacity znovu a lépe:} +Vnitřní cyklus lépe udělat nepůjde. Je potřeba alespoň lineární čas pro čiÅ¡tění. +Můžeme se ale pokusit lépe odhadnout počet iterací vnějšího cyklu. + +Sledujme stav sítě po $k$ iteracích vnějšího cyklu a pokusme se odhadnout, kolik iterací +jeÅ¡tě algoritmus udělá. Označme~$l$ délku nejkratší $st$-cesty. +Víme, že $l>k$, protože v každé iteraci vzroste $l$ alespoň o 1. + +Máme tok $f_k$ a chceme dostat maximální tok $f$. Rozdíl $f-f_k$ je tok v~síti rezerv +(tok v~původní síti to ovÅ¡em být nemusí!), označme si ho~$f_R$. +Každá iterace velkého cyklu zlepší $f_k$ alespoň o 1. Tedy nám zbývá jeÅ¡tě +nejvýše $\vert f_R \vert$ iterací. +Proto bychom chtěli omezit velikost toku $f_R$. Například řezem. + +Najdeme v síti rezerv nějaký dost malý řez $C$. Kde ho vzít?\foot{Přeci v řeznictví. Kdepak, spíše v cukrárně. +Myslíte, že v cukrárně mají Dinicovy řezy? Myslím, že v cukrárně je větÅ¡ina řezů minimální. {\sl (odposlechnuto na~přednášce)}} +Počítejme jen hrany zleva doprava. Těch je jistě nejvýše $m$ a tvoří alespoň $k$ rozhraní mezi +vrstvami. Tedy existuje rozhraní vrstev +s~nejvýše $m/k$ hranami\foot{Princip holubníku a nějaká ta $\pm1$.}. +Toto rozhraní je řez. Tedy existuje řez~$C$, pro nějž $\vert C\vert \leq m/k$, +a~algoritmu zbývá maximálně $m/k$ dalších kroků. +Celkový počet kroků je nejvýš $k + m/k$, takže stačí zvolit $k = \sqrt{m}$ a získáme +odhad na~počet kroků $\O(\sqrt{m})$. + +Tím jsme dokázali, že celková složitost Dinicova algoritmu pro jednotkové +kapacity je $\O(m^{3/2})$. Tím jsme si pomohli pro řídké grafy. \vbox{ \inlinefig{dinic-vrcholrez.eps}{0.2\hsize} -\s{Jednotkové kapacity a jeden ze stupòù roven 1:} -Úlohu hledání maximálního párování v~bipartitním grafu, pøípadnì hledání -vrcholovì disjunktních cest v~obecném grafu lze pøevést (viz pøedchozí kapitola) -na~hledání maximálního toku v~síti, v~ní¾ má ka¾dý vrchol~$v\ne s,t$ buïto vstupní -nebo výstupní stupeò roven jedné. -Pro takovou sí» mù¾eme pøedchozí odhad je¹tì tro¹ku upravit. Pokusíme -se nalézt v síti po~$k$~krocích nìjaký malý øez. Místo rozhraní budeme hledat jednu malou -vrstvu a z~malé vrstvy vytvoøíme malý øez tak, ¾e pro ka¾dý vrchol z~vrstvy vezmeme tu hranu, -která je ve~svém smìru sama. +\s{Jednotkové kapacity a jeden ze stupňů roven 1:} +Úlohu hledání maximálního párování v~bipartitním grafu, případně hledání +vrcholově disjunktních cest v~obecném grafu lze převést (viz předchozí kapitola) +na~hledání maximálního toku v~síti, v~níž má každý vrchol~$v\ne s,t$ buďto vstupní +nebo výstupní stupeň roven jedné. +Pro takovou síť můžeme předchozí odhad jeÅ¡tě troÅ¡ku upravit. Pokusíme +se nalézt v síti po~$k$~krocích nějaký malý řez. Místo rozhraní budeme hledat jednu malou +vrstvu a z~malé vrstvy vytvoříme malý řez tak, že pro každý vrchol z~vrstvy vezmeme tu hranu, +která je ve~svém směru sama. } -Po $k$ krocích máme alespoò $k$ vrstev, a~proto existuje vrstva $\delta$ s nejvý¹e $n/k$ vrcholy. -Tedy existuje øez $C$ o~velikosti $\vert C\vert \leq n/k$ (získáme z vrstvy $\delta$ vý¹e popsaným postupem). -Algoritmu zbývá do konce $\leq n/k$ iterací vnìj¹ího cyklu, celkem tedy udìlá $k + n/k$ iterací. -Nyní staèí zvolit $k = \sqrt{n}$ a slo¾itost -celého algoritmu vyjde $\O(\sqrt{n}\cdot m)$. - -Mimochodem, hledání maximálního párování pomocí Dinicova algoritmu je také ekvivalentní -známému Hopcroft-Karpovì algoritmu \cite{hopcroft:matching}. Ten je zalo¾en na~støídavých -cestách z~pøedchozí kapitoly a v~ka¾dé iteraci nalezne mno¾inu vrcholovì disjuktních -nejkrat¹ích støidavých cest, která je maximální vzhledem k~inkluzi. -Touto mno¾inou pak aktuální párování pøexoruje, èím¾ ho zvìt¹í. V¹imnìte si, ¾e tyto -mno¾iny cest odpovídají právì blokujícím tokùm v~proèi¹tìné síti rezerv, tak¾e mù¾eme -i~zde pou¾ít ná¹ odhad na~poèet iterací. - -\s{Tøetí pokus pro jednotkové kapacity bez omezení na stupnì vrcholù v síti:} -Hlavní my¹lenkou je opìt po $k$ krocích najít nìjaký malý øez. Najdeme dvì malé -sousední vrstvy a v¹echny hrany mezi nimi budou tvoøit námi hledaný malý øez. -Budeme tentokrát pøedpokládat, ¾e na¹e sí» není multigraf, pøípadnì ¾e -násobnost hran je alespoò omezena konstantou. - -Oznaème $s_i$ poèet vrcholù v $i$-té vrstvì. Souèet poètu vrcholù ve dvou -sousedních vrstvách oznaèíme $t_i = s_i + s_{i+1}$. Bude tedy platit nerovnost: +Po $k$ krocích máme alespoň $k$ vrstev, a~proto existuje vrstva $\delta$ s nejvýše $n/k$ vrcholy. +Tedy existuje řez $C$ o~velikosti $\vert C\vert \leq n/k$ (získáme z vrstvy $\delta$ výše popsaným postupem). +Algoritmu zbývá do konce $\leq n/k$ iterací vnějšího cyklu, celkem tedy udělá $k + n/k$ iterací. +Nyní stačí zvolit $k = \sqrt{n}$ a složitost +celého algoritmu vyjde $\O(\sqrt{n}\cdot m)$. + +Mimochodem, hledání maximálního párování pomocí Dinicova algoritmu je také ekvivalentní +známému Hopcroft-Karpově algoritmu \cite{hopcroft:matching}. Ten je založen na~střídavých +cestách z~předchozí kapitoly a v~každé iteraci nalezne množinu vrcholově disjuktních +nejkratších střidavých cest, která je maximální vzhledem k~inkluzi. +Touto množinou pak aktuální párování přexoruje, čímž ho zvětší. VÅ¡imněte si, že tyto +množiny cest odpovídají právě blokujícím tokům v~pročiÅ¡těné síti rezerv, takže můžeme +i~zde použít náš odhad na~počet iterací. + +\s{Třetí pokus pro jednotkové kapacity bez omezení na stupně vrcholů v síti:} +Hlavní myÅ¡lenkou je opět po $k$ krocích najít nějaký malý řez. Najdeme dvě malé +sousední vrstvy a vÅ¡echny hrany mezi nimi budou tvořit námi hledaný malý řez. +Budeme tentokrát předpokládat, že naÅ¡e síť není multigraf, případně že +násobnost hran je alespoň omezena konstantou. + +Označme $s_i$ počet vrcholů v $i$-té vrstvě. Součet počtu vrcholů ve dvou +sousedních vrstvách označíme $t_i = s_i + s_{i+1}$. Bude tedy platit nerovnost: $$\sum_i t_i \leq 2\sum_i s_i \leq 2n.$$ -Podle holubníkového principu existuje $i$ takové, ¾e $t_i \leq 2n/k$, èili -$s_i + s_{i+1} \leq 2n/k$. Poèet hran mezi $s_i$ a $s_{i+1}$ je velikost øezu -$C$, a to je shora omezeno $s_i \cdot s_{i+1}$. Nejhor¹í pøípad nastane, kdy¾ $s_i = s_{i+1} = n/k$, +Podle holubníkového principu existuje $i$ takové, že $t_i \leq 2n/k$, čili +$s_i + s_{i+1} \leq 2n/k$. Počet hran mezi $s_i$ a $s_{i+1}$ je velikost řezu +$C$, a to je shora omezeno $s_i \cdot s_{i+1}$. Nejhorší případ nastane, když $s_i = s_{i+1} = n/k$, a~proto $\vert C\vert \leq {(n/k)}^2$. -Proto poèet iterací velkého cyklu je $\leq k + {(n/k)}^2$. -Chytøe zvolíme $k = n^{2/3}$. Slo¾itost celého algoritmu pak bude $\O(n^{2/3}m)$. - -\s{Obecný odhad pro celoèíselné kapacity:} -Tento odhad je zalo¾en na velikosti -maximálního toku $f$ a pøedpokladu celoèíselných kapacit. -Za jednu iteraci velkého cyklu projdeme malým cyklem maximálnì tolikrát, -o kolik se v nìm zvedl tok, proto¾e ka¾dá zlep¹ující cesta ho zvedne alespoò o $1$. -Zlep¹ující cesta se tedy hledá maximálnì $\vert f\vert$-krát za celou dobu bìhu algoritmu. -Cestu najdeme v èase $\O(n)$. Celkem na~hledání -cest spotøebujeme $\O(\vert f\vert\cdot n)$ za celou dobu bìhu algoritmu. - -Nesmíme ale zapomenout na èi¹tìní. V jedné iteraci velkého cyklu nás stojí èi¹tìní $\O(m)$ a velkých -iterací je $\leq n$. Proto celková slo¾itost algoritmu èiní $\O(\vert f\vert n + nm)$ - -Pokud navíc budeme pøedpokládat, ¾e kapacita hran je nejvý¹e~$C$ a $G$ není multigraf, -mù¾eme vyu¾ít toho, ¾e $\vert f\vert \le Cn$ (omezeno øezem okolo~$s$) a získat odhad +Proto počet iterací velkého cyklu je $\leq k + {(n/k)}^2$. +Chytře zvolíme $k = n^{2/3}$. Složitost celého algoritmu pak bude $\O(n^{2/3}m)$. + +\s{Obecný odhad pro celočíselné kapacity:} +Tento odhad je založen na velikosti +maximálního toku $f$ a předpokladu celočíselných kapacit. +Za jednu iteraci velkého cyklu projdeme malým cyklem maximálně tolikrát, +o kolik se v něm zvedl tok, protože každá zlepÅ¡ující cesta ho zvedne alespoň o $1$. +ZlepÅ¡ující cesta se tedy hledá maximálně $\vert f\vert$-krát za celou dobu běhu algoritmu. +Cestu najdeme v čase $\O(n)$. Celkem na~hledání +cest spotřebujeme $\O(\vert f\vert\cdot n)$ za celou dobu běhu algoritmu. + +Nesmíme ale zapomenout na čiÅ¡tění. V jedné iteraci velkého cyklu nás stojí čiÅ¡tění $\O(m)$ a velkých +iterací je $\leq n$. Proto celková složitost algoritmu činí $\O(\vert f\vert n + nm)$ + +Pokud navíc budeme předpokládat, že kapacita hran je nejvýše~$C$ a $G$ není multigraf, +můžeme využít toho, že $\vert f\vert \le Cn$ (omezeno řezem okolo~$s$) a získat odhad $\O(Cn^2 + nm)$. -\h{©kálování kapacit} +\h{Å kálování kapacit} -Pokud jsou kapacity hran vìt¹í celá èísla omezená nìjakou konstantou~$C$, mù¾eme si pomoci následujícím algoritmem. -Jeho základní my¹lenka je podobná, jako u~tøídìní èísel postupnì po øádech pomocí -radix-sortu neboli pøihrádkového tøídìní. Pro jistotu si ho pøipomeòme. Algoritmus nejprve setøídí èísla podle poslední -(nejménì významné) cifry, poté podle pøedposlední, pøedpøedposlední a tak dále. +Pokud jsou kapacity hran větší celá čísla omezená nějakou konstantou~$C$, můžeme si pomoci následujícím algoritmem. +Jeho základní myÅ¡lenka je podobná, jako u~třídění čísel postupně po řádech pomocí +radix-sortu neboli přihrádkového třídění. Pro jistotu si ho připomeňme. Algoritmus nejprve setřídí čísla podle poslední +(nejméně významné) cifry, poté podle předposlední, předpředposlední a tak dále. -%\figure{dinic-sort.eps}{Kroky postupného tøídìní podle øádù}{0.4\hsize} +%\figure{dinic-sort.eps}{Kroky postupného třídění podle řádů}{0.4\hsize} -V na¹em pøípadì budeme postupnì budovat sítì èím dál podobnìj¹í zadané -síti a v~nich poèítat toky, a¾ nakonec získáme tok pro ni. +V naÅ¡em případě budeme postupně budovat sítě čím dál podobnější zadané +síti a v~nich počítat toky, až nakonec získáme tok pro ni. -Pøesnìji: Maximální tok v síti $G$ budeme hledat tak, ¾e hranám postupnì -budeme zvìt¹ovat kapacity bit po bitu v~binárním zápisu a¾ k~jejich skuteèné kapacitì. -Pøitom po~ka¾dém posunu zavoláme Dinicùv algoritmus, aby dopoèítal maximální tok. -Pomocí pøedchozího odhadu uká¾eme, ¾e jeden takový krok nebude pøíli¹ drahý. +Přesněji: Maximální tok v síti $G$ budeme hledat tak, že hranám postupně +budeme zvětÅ¡ovat kapacity bit po bitu v~binárním zápisu až k~jejich skutečné kapacitě. +Přitom po~každém posunu zavoláme Dinicův algoritmus, aby dopočítal maximální tok. +Pomocí předchozího odhadu ukážeme, že jeden takový krok nebude příliÅ¡ drahý. -\figure{dinic-scaling-original.eps}{Pùvodní sí», na hranách jsou jejich kapacity v binárním zápisu}{0.3\hsize} +\figure{dinic-scaling-original.eps}{Původní síť, na hranách jsou jejich kapacity v binárním zápisu}{0.3\hsize} -Oznaème $k$ index nejvy¹¹ího bitu v~zápisu kapacit v~zadané síti ($k = \lfloor \log_2C \rfloor$). -Postupnì budeme budovat sítì $G_i$ s~kapacitami $c_i(e) = \lfloor {c(e) / 2^{k-i}} \rfloor$. -$G_0$ je nejoøezanìj¹í sí», kde ka¾dá hrana má kapacitu rovnou nejvy¹¹ímu bitu v~binárním zápisu -její skuteèné kapacity, a¾ $G_k$ je pùvodní sí» $G$. +Označme $k$ index nejvyššího bitu v~zápisu kapacit v~zadané síti ($k = \lfloor \log_2C \rfloor$). +Postupně budeme budovat sítě $G_i$ s~kapacitami $c_i(e) = \lfloor {c(e) / 2^{k-i}} \rfloor$. +$G_0$ je nejořezanější síť, kde každá hrana má kapacitu rovnou nejvyššímu bitu v~binárním zápisu +její skutečné kapacity, až $G_k$ je původní síť $G$. -\figure{dinic-scaling-g.eps}{Sítì $G_0$, $G_1$ a $G_2$, jak vyjdou pro sí» z~pøedchozího obrázku}{0.9\hsize} +\figure{dinic-scaling-g.eps}{Sítě $G_0$, $G_1$ a $G_2$, jak vyjdou pro síť z~předchozího obrázku}{0.9\hsize} -\>Pøitom pro kapacity v~jednotlivých sítích platí: +\>Přitom pro kapacity v~jednotlivých sítích platí: $$ c_{i+1}(e) = \left\{ \eqalign{ - 2c_i(e), &\hbox{\quad pokud $(k-i-1)$-tý bit je 0,} \cr - 2c_i(e)+1, &\hbox{\quad pokud $(k-i-1)$-tý bit je 1.} \cr} + 2c_i(e), &\hbox{\quad pokud $(k-i-1)$-tý bit je 0,} \cr + 2c_i(e)+1, &\hbox{\quad pokud $(k-i-1)$-tý bit je 1.} \cr} \right. $$ -Na spoètení maximálního toku $f_i$ v síti $G_i$ zavoláme Dinicùv algoritmus, -ov¹em do zaèátku nepou¾ijeme nulový tok, nýbr¾ tok $2f_{i-1}$. Rozdíl toku z inicializace -a výsledného bude malý, toti¾: +Na spočtení maximálního toku $f_i$ v síti $G_i$ zavoláme Dinicův algoritmus, +ovÅ¡em do začátku nepoužijeme nulový tok, nýbrž tok $2f_{i-1}$. Rozdíl toku z inicializace +a výsledného bude malý, totiž: \s{Lemma:} $\vert f_i\vert - \vert 2f_{i-1}\vert \leq m.$ \proof -Vezmeme minimální øez $R$ v~$G_{i-1}$. Podle F-F vìty víme, ¾e $\vert f_{i-1}\vert = \vert R\vert$. -Øez $R$ obsahuje $\leq m$ hran, a~tedy v~$G_{i}$ má tentý¾ øez kapacitu maximálnì $2\vert R\vert+m$. -Maximální tok je omezen ka¾dým øezem, tedy i øezem $R$, a~proto tok vzroste nejvý¹e o~$m$. +Vezmeme minimální řez $R$ v~$G_{i-1}$. Podle F-F věty víme, že $\vert f_{i-1}\vert = \vert R\vert$. +Řez $R$ obsahuje $\leq m$ hran, a~tedy v~$G_{i}$ má tentýž řez kapacitu maximálně $2\vert R\vert+m$. +Maximální tok je omezen každým řezem, tedy i řezem $R$, a~proto tok vzroste nejvýše o~$m$. \qed -Podle pøedchozího odhadu pro celoèíselné kapacity výpoèet toku $f_i$ trvá $\O(mn)$. -Takový tok se bude poèítat $k$-krát, proèe¾ celková slo¾itost vyjde $\O(mn\log C)$. +Podle předchozího odhadu pro celočíselné kapacity výpočet toku $f_i$ trvá $\O(mn)$. +Takový tok se bude počítat $k$-krát, pročež celková složitost vyjde $\O(mn\log C)$. -\h{Algoritmus tøí Indù} +\h{Algoritmus tří Indů} -Pøekvapení na~konec: Dinicùv algoritmus lze pomìrnì snadno zrychlit i ve~zcela obecném -pøípadì. Malhotra, Kumar a Maheshwari vymysleli efektivnìj¹í algoritmus \cite{threeinds} -na~hledání blokujícího toku ve~vrstevnaté síti, který bì¾í v~èase $\O(n^2)$ a pou¾ijeme-li -ho v~Dinicovì algoritmu, zrychlíme hledání maximálního toku na~$\O(n^3)$. -Tento algoritmus ve¹el do~dìjin pod názvem Metoda tøí Indù. +Překvapení na~konec: Dinicův algoritmus lze poměrně snadno zrychlit i ve~zcela obecném +případě. Malhotra, Kumar a Maheshwari vymysleli efektivnější algoritmus \cite{threeinds} +na~hledání blokujícího toku ve~vrstevnaté síti, který běží v~čase $\O(n^2)$ a použijeme-li +ho v~Dinicově algoritmu, zrychlíme hledání maximálního toku na~$\O(n^3)$. +Tento algoritmus veÅ¡el do~dějin pod názvem Metoda tří Indů. -Mìjme tedy nìjakou vrstevnatou sí». Zaèneme s~nulovým tokem a budeme ho postupnì zlep¹ovat. -Prùbì¾nì si budeme udr¾ovat rezervy hran~$r(e)$\foot{poèítáme pouze rezervu ve~smìru hrany, nebo» -nám staèí najít blokující tok, ne~nutnì maximální} a také následující rezervy vrcholù: +Mějme tedy nějakou vrstevnatou síť. Začneme s~nulovým tokem a budeme ho postupně zlepÅ¡ovat. +Průběžně si budeme udržovat rezervy hran~$r(e)$\foot{počítáme pouze rezervu ve~směru hrany, neboÅ¥ +nám stačí najít blokující tok, ne~nutně maximální} a také následující rezervy vrcholů: -\s{Definice:} $r^+(v)$ je souèet rezerv v¹ech hran vstupujících do~$v$, $r^-(v)$ souèet -rezerv hran vystupujících z~$v$ a koneènì $r(v):=\min(r^+(v),r^-(v))$. +\s{Definice:} $r^+(v)$ je součet rezerv vÅ¡ech hran vstupujících do~$v$, $r^-(v)$ součet +rezerv hran vystupujících z~$v$ a konečně $r(v):=\min(r^+(v),r^-(v))$. -V~ka¾dé iteraci algoritmu nalezneme vrchol s~nejni¾¹ím~$r(v)$ a zvìt¹íme tok tak, aby se -tato rezerva vynulovala. Za~tímto úèelem nejdøíve pøepravíme $r(v)$ jednotek toku ze~zdroje -do~$v$: u~ka¾dého vrcholu~$w$ si budeme pamatovat {\I plán} $p(w)$, co¾ bude mno¾ství -tekutiny, které potøebujeme dostat ze~zdroje do~$w$. Nejdøíve budou plány v¹ude nulové -a¾ na~$p(v)=r(v)$. Pak budeme postupovat po~vrstvách smìrem ke~zdroji a plány v¹ech -vrcholù splníme tak, ¾e je pøevedeme na~plány vrcholù v~následující vrstvì, a¾ doputujeme -ke~zdroji, jeho¾ plán je splnìn triviálnì. Nakonec analogickým zpùsobem protlaèíme $r(v)$ -jednotek z~$v$ do~spotøebièe. +V~každé iteraci algoritmu nalezneme vrchol s~nejnižším~$r(v)$ a zvětšíme tok tak, aby se +tato rezerva vynulovala. Za~tímto účelem nejdříve přepravíme $r(v)$ jednotek toku ze~zdroje +do~$v$: u~každého vrcholu~$w$ si budeme pamatovat {\I plán} $p(w)$, což bude množství +tekutiny, které potřebujeme dostat ze~zdroje do~$w$. Nejdříve budou plány vÅ¡ude nulové +až na~$p(v)=r(v)$. Pak budeme postupovat po~vrstvách směrem ke~zdroji a plány vÅ¡ech +vrcholů splníme tak, že je převedeme na~plány vrcholů v~následující vrstvě, až doputujeme +ke~zdroji, jehož plán je splněn triviálně. Nakonec analogickým způsobem protlačíme $r(v)$ +jednotek z~$v$ do~spotřebiče. -Bìhem výpoètu prùbì¾nì pøepoèítáváme v¹echna $r^+$, $r^-$ a~$r$ podle toho, jak se mìní -rezervy jednotlivých hran (pøi ka¾dé úpravì rezervy to zvládneme v~konstantním èase) -a sí» èistíme stejnì jako u~Dinicova algoritmu. +Během výpočtu průběžně přepočítáváme vÅ¡echna $r^+$, $r^-$ a~$r$ podle toho, jak se mění +rezervy jednotlivých hran (při každé úpravě rezervy to zvládneme v~konstantním čase) +a síť čistíme stejně jako u~Dinicova algoritmu. \finalfix{\goodbreak} -\s{Algoritmus:} (hledání blokujícího toku ve~vrstevnaté síti podle tøí Indù) +\s{Algoritmus:} (hledání blokujícího toku ve~vrstevnaté síti podle tří Indů) \algo -\:$f_B\leftarrow\$. -\:Spoèítáme rezervy v¹ech hran a $r^+$, $r^-$ a $r$ v¹ech vrcholù. (Tyto hodnoty - budeme posléze udr¾ovat pøi ka¾dé zmìnì toku po~hranì.) -\:Dokud v~síti existují vrcholy s~nenulovou rezervou, vezmeme vrchol $v$ s~nejmen¹ím $r(v)$ - a provedeme pro nìj: {\I (vnìj¹í cyklus)} -\::Pøevedeme $r(v)$ jednotek toku z~$s$ do~$v$ následovnì: -\:::Polo¾íme $p(v)\leftarrow r(v)$, $p(\cdot)=0$. -\:::Procházíme vrcholy sítì po~vrstvách od~$v$ smìrem k~$s$. Pro ka¾dý vrchol~$w$ provedeme: +\:$f_B\leftarrow\$. +\:Spočítáme rezervy vÅ¡ech hran a $r^+$, $r^-$ a $r$ vÅ¡ech vrcholů. (Tyto hodnoty + budeme posléze udržovat při každé změně toku po~hraně.) +\:Dokud v~síti existují vrcholy s~nenulovou rezervou, vezmeme vrchol $v$ s~nejmenším $r(v)$ + a provedeme pro něj: {\I (vnější cyklus)} +\::Převedeme $r(v)$ jednotek toku z~$s$ do~$v$ následovně: +\:::Položíme $p(v)\leftarrow r(v)$, $p(\cdot)=0$. +\:::Procházíme vrcholy sítě po~vrstvách od~$v$ směrem k~$s$. Pro každý vrchol~$w$ provedeme: \::::Dokud $p(w)>0$: -\:::::Vezmeme libovolnou hranu $uw$ a tok po~ní zvý¹íme o~$\delta=\min(r(uw), p(w))$. Tím se - $p(w)$ sní¾í~o~$\delta$ a $p(u)$ zvý¹í~o~$\delta$. -\:::::Pokud se hrana~$uw$ nasytila, odstraníme jí ze sítì a sí» doèistíme. -\::Analogicky pøevedeme $r(v)$ jednotek z~$v$ do~$t$. +\:::::Vezmeme libovolnou hranu $uw$ a tok po~ní zvýšíme o~$\delta=\min(r(uw), p(w))$. Tím se + $p(w)$ sníží~o~$\delta$ a $p(u)$ zvýší~o~$\delta$. +\:::::Pokud se hrana~$uw$ nasytila, odstraníme jí ze sítě a síť dočistíme. +\::Analogicky převedeme $r(v)$ jednotek z~$v$ do~$t$. \endalgo -\s{Analýza:} Nejprve si v¹imneme, ¾e cyklus v~kroku~8 opravdu doká¾e vynulovat $p(w)$. -Souèet v¹ech $p(w)$ pøes ka¾dou vrstvu je toti¾ nejvý¹e roven $r(v)$, tak¾e speciálnì ka¾dé -$p(w)\le r(v)$. Jen¾e $r(v)$ jsme vybrali jako nejmen¹í, tak¾e $p(w)\le r(v)\le r(w)\le r^+(w)$, -a~proto je plánovaný tok kudy pøivést. Proto se algoritmus zastaví a vydá blokující tok. - -Zbývá odhadnout èasovou slo¾itost: Kdy¾ oddìlíme pøevádìní plánù po~hranách (kroky 7--9), -zbytek jedné iterace vnìj¹ího cyklu trvá~$\O(n)$ a tìchto iterací je nejvý¹e~$n$. V¹echna pøevedení -plánu si rozdìlíme na~ta, kterými se nìjaká hrana nasytila, a~ta, která skonèila vynulováním $p(w)$. -Tìch prvních je $\O(m)$, proto¾e ka¾dou takovou hranu vzápìtí odstraníme a èi¹tìní, jak u¾ víme, -trvá také lineárnì dlouho. Druhý pøípad nastane pro ka¾dý vrchol nejvý¹e jednou za~iteraci. -Dohromady tedy trvají v¹echna pøevedení $\O(n^2)$, stejnì jako zbytek algoritmu. +\s{Analýza:} Nejprve si vÅ¡imneme, že cyklus v~kroku~8 opravdu dokáže vynulovat $p(w)$. +Součet vÅ¡ech $p(w)$ přes každou vrstvu je totiž nejvýše roven $r(v)$, takže speciálně každé +$p(w)\le r(v)$. Jenže $r(v)$ jsme vybrali jako nejmenší, takže $p(w)\le r(v)\le r(w)\le r^+(w)$, +a~proto je plánovaný tok kudy přivést. Proto se algoritmus zastaví a vydá blokující tok. + +Zbývá odhadnout časovou složitost: Když oddělíme převádění plánů po~hranách (kroky 7--9), +zbytek jedné iterace vnějšího cyklu trvá~$\O(n)$ a těchto iterací je nejvýše~$n$. VÅ¡echna převedení +plánu si rozdělíme na~ta, kterými se nějaká hrana nasytila, a~ta, která skončila vynulováním $p(w)$. +Těch prvních je $\O(m)$, protože každou takovou hranu vzápětí odstraníme a čiÅ¡tění, jak už víme, +trvá také lineárně dlouho. Druhý případ nastane pro každý vrchol nejvýše jednou za~iteraci. +Dohromady tedy trvají vÅ¡echna převedení $\O(n^2)$, stejně jako zbytek algoritmu. \qed -\h{Pøehled variant Dinicova algoritmu} +\h{Přehled variant Dinicova algoritmu} \medskip \centerline{\vbox{\halign{# \hfil \quad &# \hfil \cr -\it varianta &\it èas \cr\noalign{\smallskip\hrule\smallskip} -standardní &$\O(n^2m)$ \cr -jednotkové kapacity &$\O(\sqrt{m}\cdot m) = \O(m^{3/2})$ \cr -jednotkové kapacity, 1 stupeò $\leq 1$ &$\O(\sqrt{n}\cdot m)$ \cr -jednotkové kapacity, prostý graf &$\O(n^{2/3}m)$ \cr -celoèíselné kapacity &$\O(\vert f\vert\cdot n + nm)$ \cr -celoèíselné kapacity $ \leq C$ &$\O(Cn^2 + mn)$ \cr -celoèíselné kapacity $ \leq C$ (¹kálování)&$\O(mn\log C)$ \cr -tøi Indové &$\O(n^3)$ \cr +\it varianta &\it čas \cr\noalign{\smallskip\hrule\smallskip} +standardní &$\O(n^2m)$ \cr +jednotkové kapacity &$\O(\sqrt{m}\cdot m) = \O(m^{3/2})$ \cr +jednotkové kapacity, 1 stupeň $\leq 1$ &$\O(\sqrt{n}\cdot m)$ \cr +jednotkové kapacity, prostý graf &$\O(n^{2/3}m)$ \cr +celočíselné kapacity &$\O(\vert f\vert\cdot n + nm)$ \cr +celočíselné kapacity $ \leq C$ &$\O(Cn^2 + mn)$ \cr +celočíselné kapacity $ \leq C$ (Å¡kálování)&$\O(mn\log C)$ \cr +tři Indové &$\O(n^3)$ \cr }}} \references diff --git a/3-bipcon/3-bipcon.tex b/3-bipcon/3-bipcon.tex index eaa49c9..362bd7b 100644 --- a/3-bipcon/3-bipcon.tex +++ b/3-bipcon/3-bipcon.tex @@ -1,120 +1,120 @@ \input ../sgr.tex -\prednaska{3}{Bipartitní párování a globální k-souvislost}{} - -V~pøede¹lých kapitolách jsme se zabývali aplikacemi tokù na~hledání maximálního párování -a minimálního $st$-øezu. Nyní si pøedvedeme dva algoritmy pro podobné problémy, -které se obejdou bez tokù. - -\h{Maximální párování v regulárním bipartitním grafu \cite{alon:matching}} - -Nejprve si nadefinujme operaci {\I ¹tìpení grafu,} která zadaný graf $G=(V,E)$ -se v¹emi vrcholy sudého stupnì a sudým poètem hran v~ka¾dé komponentì souvislosti -rozlo¾í na~disjunktní podgrafy $G_1=(V,E_1)$ a $G_2=(V,E_2)$, -v~nich¾ bude pro ka¾dý vrchol~$v$ platit ${\rm deg}_{G_1}(v) = {\rm -deg}_{G_2}(v) = {\rm deg}_G(v)/2$. Tuto operaci mù¾eme snadno -provést v~lineárním èase tak, ¾e si graf rozdìlíme na~komponenty, v~ka¾dé -nalezneme eulerovský tah a jeho hrany budeme pøidávat støídavì do~$G_1$ a do~$G_2$. - -©tìpení nám pomù¾e ke~snadnému algoritmu pro nalezení maximálního párování ve~$2^t$-regulárním -bipartitním grafu.\foot{V¹imnìte si, ¾e takové párování bude v¾dy perfektní (viz Hallova vìta).} -Komponenty takového grafu mají urèitì sudý poèet hran, tak¾e jej mù¾eme -roz¹tìpit na~dva $2^{t-1}$-regulární grafy. Libovolný jeden z~nich pak opìt roz¹tìpíme -atd., a¾ dostaneme $1$-regulární graf, který je perfektním párováním v~$G$. -To v¹e jsme schopni stihnout v~lineárním èase, jeliko¾ velikosti grafù, které -¹tìpíme, exponenciálnì klesají. Také bychom mohli rekurzivnì zpracovávat obì -èásti a tak se v~èase $\O(m\log n)$ dobrat ke~kompletní 1-faktorizaci -zadaného grafu.\foot{To je rozklad hran grafu na~disjunktní perfektní párování -a má ho ka¾dý regulární bipartitní graf.} - -Pokud zadaný graf nebude $2^t$-regulární, pomù¾eme si tím, ¾e ho novými hranami -doplníme na $2^t$-regulární a pak si pøi ¹tìpeních budeme vybírat ten podgraf, -do~kterého padlo ménì nových hran, a uká¾eme, ¾e nakonec v¹echny zmizí. -Abychom graf pøíli¹ nezvìt¹ili, budeme se sna¾it místo pøidávání úplnì nových -hran pouze zvy¹ovat násobnost hran existujících. Pro ka¾dou hranu $e$ si tedy -budeme pamatovat její násobnost $n(e)$. - -{\I ©tìpení grafu s~násobnostmi} pak budeme provádìt následovnì: hranu~$e$ -s~násobností $n(e)$ umístíme do~$G_1$ i~do~$G_2$ s~násobností $\lfloor n(e)/2 -\rfloor$ a pokud bylo $n(e)$ liché, pøidáme hranu do~pomocného grafu -$G^\prime$. V¹imnìte si, ¾e $G^\prime$ bude graf bez násobností, v~nìm¾ mají -v¹echny vrcholy sudý stupeò, tak¾e na~nìj mù¾eme aplikovat pùvodní ¹tìpící algoritmus -a $G^\prime_i$ pøiøadit ke~$G_i$. To~v¹e zvládneme v~èase $\O(m)$. - -Mìjme nyní $k$-regulární bipartitní graf. Obì jeho partity jsou stejnì velké, -oznaème si poèet vrcholù v~ka¾dé z~nich~$n$. Zvolme $t$ tak aby $2^t\geq kn$. -Zvolme dále parametry +\prednaska{3}{Bipartitní párování a globální k-souvislost}{} + +V~předeÅ¡lých kapitolách jsme se zabývali aplikacemi toků na~hledání maximálního párování +a minimálního $st$-řezu. Nyní si předvedeme dva algoritmy pro podobné problémy, +které se obejdou bez toků. + +\h{Maximální párování v regulárním bipartitním grafu \cite{alon:matching}} + +Nejprve si nadefinujme operaci {\I Å¡těpení grafu,} která zadaný graf $G=(V,E)$ +se vÅ¡emi vrcholy sudého stupně a sudým počtem hran v~každé komponentě souvislosti +rozloží na~disjunktní podgrafy $G_1=(V,E_1)$ a $G_2=(V,E_2)$, +v~nichž bude pro každý vrchol~$v$ platit ${\rm deg}_{G_1}(v) = {\rm +deg}_{G_2}(v) = {\rm deg}_G(v)/2$. Tuto operaci můžeme snadno +provést v~lineárním čase tak, že si graf rozdělíme na~komponenty, v~každé +nalezneme eulerovský tah a jeho hrany budeme přidávat střídavě do~$G_1$ a do~$G_2$. + +Å těpení nám pomůže ke~snadnému algoritmu pro nalezení maximálního párování ve~$2^t$-regulárním +bipartitním grafu.\foot{VÅ¡imněte si, že takové párování bude vždy perfektní (viz Hallova věta).} +Komponenty takového grafu mají určitě sudý počet hran, takže jej můžeme +rozÅ¡těpit na~dva $2^{t-1}$-regulární grafy. Libovolný jeden z~nich pak opět rozÅ¡těpíme +atd., až dostaneme $1$-regulární graf, který je perfektním párováním v~$G$. +To vÅ¡e jsme schopni stihnout v~lineárním čase, jelikož velikosti grafů, které +Å¡těpíme, exponenciálně klesají. Také bychom mohli rekurzivně zpracovávat obě +části a tak se v~čase $\O(m\log n)$ dobrat ke~kompletní 1-faktorizaci +zadaného grafu.\foot{To je rozklad hran grafu na~disjunktní perfektní párování +a má ho každý regulární bipartitní graf.} + +Pokud zadaný graf nebude $2^t$-regulární, pomůžeme si tím, že ho novými hranami +doplníme na $2^t$-regulární a pak si při Å¡těpeních budeme vybírat ten podgraf, +do~kterého padlo méně nových hran, a ukážeme, že nakonec vÅ¡echny zmizí. +Abychom graf příliÅ¡ nezvětÅ¡ili, budeme se snažit místo přidávání úplně nových +hran pouze zvyÅ¡ovat násobnost hran existujících. Pro každou hranu $e$ si tedy +budeme pamatovat její násobnost $n(e)$. + +{\I Å těpení grafu s~násobnostmi} pak budeme provádět následovně: hranu~$e$ +s~násobností $n(e)$ umístíme do~$G_1$ i~do~$G_2$ s~násobností $\lfloor n(e)/2 +\rfloor$ a pokud bylo $n(e)$ liché, přidáme hranu do~pomocného grafu +$G^\prime$. VÅ¡imněte si, že $G^\prime$ bude graf bez násobností, v~němž mají +vÅ¡echny vrcholy sudý stupeň, takže na~něj můžeme aplikovat původní Å¡těpící algoritmus +a $G^\prime_i$ přiřadit ke~$G_i$. To~vÅ¡e zvládneme v~čase $\O(m)$. + +Mějme nyní $k$-regulární bipartitní graf. Obě jeho partity jsou stejně velké, +označme si počet vrcholů v~každé z~nich~$n$. Zvolme $t$ tak aby $2^t\geq kn$. +Zvolme dále parametry $\alpha := \lfloor 2^t/k \rfloor$ a $\beta := 2^t \bmod k$. -Ka¾dé pùvodní hranì nastavíme násobnost~$\alpha$ a pøidáme triviální párování~$F$ -($i$-tý vrchol vlevo se spojí s~$i$-tým vrcholem vpravo) s~násobností~$\beta$. -V¹imnìte si, ¾e $\betai$, $v_i$ a $v_j$ jsou oddìleny øezem $C$ a $j$ je minimální takové. -[Tedy $v_j$ je nejbli¾¹í vrchol na~druhé stranì øezu.] +\:$u_i := v_j$ tak, že $j>i$, $v_i$ a $v_j$ jsou odděleny řezem $C$ a $j$ je minimální takové. +[Tedy $v_j$ je nejbližší vrchol na~druhé straně řezu.] \endalgo -Ka¾dé $u_{i-1}$ je tedy buï rovno $u_i$, pokud jsou $v_i$ a $v_{i-1}$ na stejné stranì øezu, nebo rovno $v_i$, pokud -jsou $v_i$ a $v_{i-1}$ na~stranách opaèných. Z~toho dostáváme, ¾e $d(\{v_1\ldots v_{i-1}\},u_i)\leq d(\{v_1\ldots -v_{i-1}\},u_{i-1})$, proto¾e buïto $u_{i-1}=u_i$, a pak je nerovnost splnìna jako rovnost, nebo je $u_{i-1}=v_i$ a -nerovnost plyne z~legálnosti uspoøádání. +Každé $u_{i-1}$ je tedy buď rovno $u_i$, pokud jsou $v_i$ a $v_{i-1}$ na stejné straně řezu, nebo rovno $v_i$, pokud +jsou $v_i$ a $v_{i-1}$ na~stranách opačných. Z~toho dostáváme, že $d(\{v_1\ldots v_{i-1}\},u_i)\leq d(\{v_1\ldots +v_{i-1}\},u_{i-1})$, protože buďto $u_{i-1}=u_i$, a pak je nerovnost splněna jako rovnost, nebo je $u_{i-1}=v_i$ a +nerovnost plyne z~legálnosti uspořádání. -Chceme ukázat, ¾e velikost na¹eho øezu~$C$ je alespoò taková, jako velikost øezu kolem vrcholu $v_n$. -V¹imneme si, ¾e $\vert C \vert \geq \sum_{i=1}^{n-1} d(v_i,u_i)$. Hrany mezi $v_i$ a $u_i$ jsou toti¾ navzájem -rùzné a ka¾dá z~nich je souèástí øezu~$C$. Uká¾eme, ¾e pravá strana je alespoò $d(v_n)$: +Chceme ukázat, že velikost naÅ¡eho řezu~$C$ je alespoň taková, jako velikost řezu kolem vrcholu $v_n$. +VÅ¡imneme si, že $\vert C \vert \geq \sum_{i=1}^{n-1} d(v_i,u_i)$. Hrany mezi $v_i$ a $u_i$ jsou totiž navzájem +různé a každá z~nich je součástí řezu~$C$. Ukážeme, že pravá strana je alespoň $d(v_n)$: $$\eqalign{ \sum_{i=1}^{n-1} d(v_i,u_i) &= \sum_{i=1}^{n-1} d(\{v_1\ldots v_i\},u_i) - d(\{v_1 \ldots v_{i-1}\},u_i) \geq \cr &\geq \sum_{i=1}^{n-1} d(\{v_1 \ldots v_i\},u_i) - d(\{v_1 \ldots v_{i-1}\},u_{i-1}) = \cr @@ -123,28 +123,28 @@ $$\eqalign{ }$$ \qed -Dokázali jsme, ¾e libovolný øez separující $v_{n-1}$ a $v_n$ je alespoò tak velký jako jednoduchý øez skládající se jen z hran -kolem~$v_n$. Kdy¾ tedy sestavíme nìjakou LU posloupnost vrcholù, budeme mít k dispozici jednoduchý minimální øez -$v_{n-1}$ a~$v_n$. Následnì vytvoøíme graf $G'$, v nìm¾ $v_{n-1}$ a $v_n$ kontrahujeme. Rekurzivnì najdeme minimální -øez v $G'$ (sestrojíme nové LU atd.). Hledaný minimální øez poté buïto oddìluje vrcholy $v_n$ a $v_{n-1}$, a potom je øez -kolem vrcholu $v_n$ minimální, nebo vrcholy $v_n$ a $v_{n-1}$ neoddìluje, a v takovém pøípadì jej najdeme -rekurzivnì. Hledaný øez je tedy men¹í z rekurzivnì nalezeného øezu a øezu kolem $v_n$. - -Zbývá ukázat, jak konstruovat LU. Postaèí hladovì: Pamatujeme si $\forall v\neq v_1 \ldots v_{i-1}$ hodnotu $d(\{v_1 \ldots v_{i-1}\},v)$, oznaème ji $z_v$. V ka¾dém kroku vybereme vrchol $v$ s maximální hodnotou $z_v$, prohlásíme ho za $v_i$ a pøepoèítáme~$z_v$. - -Zde se hodí datová struktura, která doká¾e rychle hledat maxima a zvy¹ovat hodnoty prvkù, -napøíklad Fibonacciho halda. Ta zvládne \ v~èase $\O(\log n)$ a \ v~$\O(1)$ -amortizovanì. Celkem pak ná¹ algoritmus bude mít slo¾itost $\O(n(m+n\log n))$ pro obecné kapacity. - -Pokud jsou kapacity malá celá èísla, mù¾eme vyu¾ít pøihrádkové struktury. Budeme -si udr¾ovat obousmìrný seznam zatím pou¾itých hodnot $z_v$, ka¾dý prvek takového -seznamu bude obsahovat v¹echny vrcholy se spoleènou hodnotou $z_v$. Kdy¾ budeme -mít seznam seøazený, vybrání minimálního prvku bude znamenat pouze podívat se na -první prvek seznamu a z nìj odebrat jeden vrchol, pøípadnì celý prvek ze seznamu -odstranit. Operace \ poté bude reprezentovat pouze pøesunutí vrcholu o -malý poèet pøihrádek, pøípadnì zalo¾ení nové pøihrádky na správném místì. -\ proto bude mít slo¾itost $\O(1)$, v¹echny \ dohromady $\O(m)$, -jeliko¾ za~ka¾dou hranu pøeskakujeme maximálnì jednu pøihrádku, a celý algoritmus $\O(mn)$. +Dokázali jsme, že libovolný řez separující $v_{n-1}$ a $v_n$ je alespoň tak velký jako jednoduchý řez skládající se jen z hran +kolem~$v_n$. Když tedy sestavíme nějakou LU posloupnost vrcholů, budeme mít k dispozici jednoduchý minimální řez +$v_{n-1}$ a~$v_n$. Následně vytvoříme graf $G'$, v němž $v_{n-1}$ a $v_n$ kontrahujeme. Rekurzivně najdeme minimální +řez v $G'$ (sestrojíme nové LU atd.). Hledaný minimální řez poté buďto odděluje vrcholy $v_n$ a $v_{n-1}$, a potom je řez +kolem vrcholu $v_n$ minimální, nebo vrcholy $v_n$ a $v_{n-1}$ neodděluje, a v takovém případě jej najdeme +rekurzivně. Hledaný řez je tedy menší z rekurzivně nalezeného řezu a řezu kolem $v_n$. + +Zbývá ukázat, jak konstruovat LU. Postačí hladově: Pamatujeme si $\forall v\neq v_1 \ldots v_{i-1}$ hodnotu $d(\{v_1 \ldots v_{i-1}\},v)$, označme ji $z_v$. V každém kroku vybereme vrchol $v$ s maximální hodnotou $z_v$, prohlásíme ho za $v_i$ a přepočítáme~$z_v$. + +Zde se hodí datová struktura, která dokáže rychle hledat maxima a zvyÅ¡ovat hodnoty prvků, +například Fibonacciho halda. Ta zvládne \ v~čase $\O(\log n)$ a \ v~$\O(1)$ +amortizovaně. Celkem pak náš algoritmus bude mít složitost $\O(n(m+n\log n))$ pro obecné kapacity. + +Pokud jsou kapacity malá celá čísla, můžeme využít přihrádkové struktury. Budeme +si udržovat obousměrný seznam zatím použitých hodnot $z_v$, každý prvek takového +seznamu bude obsahovat vÅ¡echny vrcholy se společnou hodnotou $z_v$. Když budeme +mít seznam seřazený, vybrání minimálního prvku bude znamenat pouze podívat se na +první prvek seznamu a z něj odebrat jeden vrchol, případně celý prvek ze seznamu +odstranit. Operace \ poté bude reprezentovat pouze přesunutí vrcholu o +malý počet přihrádek, případně založení nové přihrádky na správném místě. +\ proto bude mít složitost $\O(1)$, vÅ¡echny \ dohromady $\O(m)$, +jelikož za~každou hranu přeskakujeme maximálně jednu přihrádku, a celý algoritmus $\O(mn)$. \references \bye diff --git a/4-ght/4-ght.tex b/4-ght/4-ght.tex index 5e988e6..1aba6f5 100644 --- a/4-ght/4-ght.tex +++ b/4-ght/4-ght.tex @@ -3,246 +3,246 @@ \def\st{$st$} \def\rr{$r_1r_2$} \def\GHT{GHT} -\def\PGHT{ÈGHT} +\def\PGHT{ČGHT} \input ../sgr.tex \prednaska{4}{Gomory-Hu Trees}{} -Cílem této kapitoly je popsat datovou strukturu, která velice kompaktnì -popisuje minimální $st$-øezy pro v¹echny dvojice vrcholù $s,t$ v~daném -neorientovaném grafu. Tuto strukturu poprvé popsali Gomory a Hu v~èlánku \cite{gomoryhu}. +Cílem této kapitoly je popsat datovou strukturu, která velice kompaktně +popisuje minimální $st$-řezy pro vÅ¡echny dvojice vrcholů $s,t$ v~daném +neorientovaném grafu. Tuto strukturu poprvé popsali Gomory a Hu v~článku \cite{gomoryhu}. -Zatím umíme nalézt minimální \st-øez pro zadanou dvojici vrcholù v~neorientovaném -grafu v~èase $\tau=\O(n^{2/3}m)$ pro~jednotkové kapacity, $\O(n^2m)$ pro obecné. -Nalézt minimální \st-øez pro ka¾dou dvojici vrcholù -bychom tedy dokázali v~èase $\O(n^2\tau)$. Tento výsledek budeme -chtít zlep¹it. +Zatím umíme nalézt minimální \st-řez pro zadanou dvojici vrcholů v~neorientovaném +grafu v~čase $\tau=\O(n^{2/3}m)$ pro~jednotkové kapacity, $\O(n^2m)$ pro obecné. +Nalézt minimální \st-řez pro každou dvojici vrcholů +bychom tedy dokázali v~čase $\O(n^2\tau)$. Tento výsledek budeme +chtít zlepÅ¡it. -\s{Znaèení:} Máme\li{} graf $(V,E)$ a $U\subseteq V$, $\d(U)$ znaèí hrany vedoucí -mezi $U$ a $\overline U$, formálnì tedy $\d(U)=E \cap ((U \times \overline U) \cup (\overline U \times U))$. -Kapacitu øezu $\d(W)$ budeme znaèit $d(W)$ a $r(s,t)$ bude kapacita nejmen¹ího \st-øezu. +\s{Značení:} Máme\li{} graf $(V,E)$ a $U\subseteq V$, $\d(U)$ značí hrany vedoucí +mezi $U$ a $\overline U$, formálně tedy $\d(U)=E \cap ((U \times \overline U) \cup (\overline U \times U))$. +Kapacitu řezu $\d(W)$ budeme značit $d(W)$ a $r(s,t)$ bude kapacita nejmenšího \st-řezu. -\s{Pozorování:} Minimální øez rozdìluje graf jen na~dvì komponenty (v¹imnìte si, ¾e pro -separátory nic takového neplatí) a ka¾dý minimální øez je tím pádem v¾dy mo¾né zapsat jako $\d(W)$ -pro nìjakou mno¾inu $W\subset V$. +\s{Pozorování:} Minimální řez rozděluje graf jen na~dvě komponenty (vÅ¡imněte si, že pro +separátory nic takového neplatí) a každý minimální řez je tím pádem vždy možné zapsat jako $\d(W)$ +pro nějakou množinu $W\subset V$. \h{Gomory-Hu Tree} -\s{Definice:} {\I Gomory-Hu Tree} (dále jen \GHT) pro neorientovaný nezápornì ohodnocený graf $G=(V,E)$ -je strom $T=(V,F)$ takový, ¾e pro ka¾dou hranu $st\in F$ platí: Oznaèíme-li $K_1$ a $K_2$ -komponenty lesa $T\setminus st$, je $\d(K_1)=\d(K_2)$ minimální \st-øez. -[Pozor, $F$ nemusí být podmno¾ina pùvodních hran $E$.] +\s{Definice:} {\I Gomory-Hu Tree} (dále jen \GHT) pro neorientovaný nezáporně ohodnocený graf $G=(V,E)$ +je strom $T=(V,F)$ takový, že pro každou hranu $st\in F$ platí: Označíme-li $K_1$ a $K_2$ +komponenty lesa $T\setminus st$, je $\d(K_1)=\d(K_2)$ minimální \st-řez. +[Pozor, $F$ nemusí být podmnožina původních hran $E$.] -\s{Dal¹í znaèení:} Pro $e\in F$ budeme øezem $\d(e)$ oznaèovat øez $\d(K_1)=\d(K_2)$ a $r(e)$ bude jeho kapacita. +\s{Další značení:} Pro $e\in F$ budeme řezem $\d(e)$ označovat řez $\d(K_1)=\d(K_2)$ a $r(e)$ bude jeho kapacita. -\>K~èemu takový \GHT{} je (existuje-li)? To nám poví následující vìta: +\>K~čemu takový \GHT{} je (existuje-li)? To nám poví následující věta: -\s{Vìta (o~vyu¾ití \GHT):} Buï $T$ libovolný \GHT{} pro graf~$G$ a mìjme dva vrcholy $s$ a $t$. Dále -nech» $P$ je cesta v~$T$ mezi vrcholy $s$ a $t$ a $e$ je hrana na cestì $P$ s~minimálním $r(e)$. -Pak $\d(e)$ je minimální \st-øez v~$G$. +\s{Věta (o~využití \GHT):} Buď $T$ libovolný \GHT{} pro graf~$G$ a mějme dva vrcholy $s$ a $t$. Dále +nechÅ¥ $P$ je cesta v~$T$ mezi vrcholy $s$ a $t$ a $e$ je hrana na cestě $P$ s~minimálním $r(e)$. +Pak $\d(e)$ je minimální \st-řez v~$G$. -\proof Nejprve si doká¾eme jedno drobné lemmátko: +\proof Nejprve si dokážeme jedno drobné lemmátko: {\advance\leftskip by 2em\advance\rightskip by 2em -\s{Lemmátko:} Pro ka¾dou trojici vrcholù $x,y,z$ platí, ¾e: +\s{Lemmátko:} Pro každou trojici vrcholů $x,y,z$ platí, že: $$r(x,z) \ge \min(r(x,y),r(y,z)).$$ -\proof Buï $W$ minimální $xz$-øez. +\proof Buď $W$ minimální $xz$-řez. \fig{4-ght-rez.eps}{\epsfxsize} -\noindent Vrchol $y$ musí být v~jedné z~komponent, Pokud je v~komponentì s~$x$, pak $r(y,z) \le d(W)$, -proto¾e $\d(W)$ je také $yz$-øez. Pokud v~té druhé, analogicky platí $r(x,y) \le d(W)$. +\noindent Vrchol $y$ musí být v~jedné z~komponent, Pokud je v~komponentě s~$x$, pak $r(y,z) \le d(W)$, +protože $\d(W)$ je také $yz$-řez. Pokud v~té druhé, analogicky platí $r(x,y) \le d(W)$. \qed } -\noindent Zpìt k~dùkazu vìty: -Chceme dokázat, ¾e $\d(e)$ je minimální \st-øez. To, ¾e je to nìjaký øez, plyne z~definice \GHT. -Minimalitu doká¾eme indukcí podle délky cesty $P$: +\noindent Zpět k~důkazu věty: +Chceme dokázat, že $\d(e)$ je minimální \st-řez. To, že je to nějaký řez, plyne z~definice \GHT. +Minimalitu dokážeme indukcí podle délky cesty $P$: \itemize\ibull -\:$\vert\,P\,\vert = 1$: Hrana $e$ je v~tomto pøípadì pøímo $st$, tak¾e i minimalita plyne z~definice \GHT. -\:$\vert\,P\,\vert > 1$: Cesta $P$ spojuje vrcholy $s$ a $t$, její první hranu oznaème $sx$. -Na¹e právì dokázané lemmátko øíká, ¾e $r(s,t) \ge \min (r(s,x),r(x,t))$. -Urèitì je pravda, ¾e $r(s,x) \ge r(e)$, proto¾e $e$ byla hrana cesty $P$ s~nejmen¹ím $r(e)$. -To, ¾e $r(x,t) \ge r(e)$, plyne z~indukèního pøedpokladu, proto¾e cesta mezi $x$ a $t$ -je krat¹í ne¾ cesta $P$. Dostáváme tak, ¾e $r(s,t) \ge \min(r(s,x),r(x,t)) \ge r(e)$. +\:$\vert\,P\,\vert = 1$: Hrana $e$ je v~tomto případě přímo $st$, takže i minimalita plyne z~definice \GHT. +\:$\vert\,P\,\vert > 1$: Cesta $P$ spojuje vrcholy $s$ a $t$, její první hranu označme $sx$. +NaÅ¡e právě dokázané lemmátko říká, že $r(s,t) \ge \min (r(s,x),r(x,t))$. +Určitě je pravda, že $r(s,x) \ge r(e)$, protože $e$ byla hrana cesty $P$ s~nejmenším $r(e)$. +To, že $r(x,t) \ge r(e)$, plyne z~indukčního předpokladu, protože cesta mezi $x$ a $t$ +je kratší než cesta $P$. Dostáváme tak, že $r(s,t) \ge \min(r(s,x),r(x,t)) \ge r(e)$. \qeditem \endlist -Pokud doká¾eme \GHT{} sestrojit, nalézt minimální \st-øez pro libovolnou dvojici vrcholù -doká¾eme stejnì rychle jako nalézt hranu s~nejmen¹í kapacitou na cestì mezi $s$ a $t$ v~\GHT. -K~tomu mù¾eme pou¾ít napøíklad Sleator-Tarjanovy stromy, které tuto operaci -doká¾ou provést v~amortizovaném èase $\O(\log n)$, nebo mù¾eme vyu¾ít toho, -¾e máme spoustu èasu na~pøedvýpoèet, a minimální hrany si pro ka¾dou dvojici -prostì pøichystat pøedem. Také lze vymyslet redukci na problém nalezení spoleèného -pøedchùdce vrcholù ve stromì (nebude to \GHT) a pou¾ít jedno z~øe¹ení tohoto problému. +Pokud dokážeme \GHT{} sestrojit, nalézt minimální \st-řez pro libovolnou dvojici vrcholů +dokážeme stejně rychle jako nalézt hranu s~nejmenší kapacitou na cestě mezi $s$ a $t$ v~\GHT. +K~tomu můžeme použít například Sleator-Tarjanovy stromy, které tuto operaci +dokážou provést v~amortizovaném čase $\O(\log n)$, nebo můžeme využít toho, +že máme spoustu času na~předvýpočet, a minimální hrany si pro každou dvojici +prostě přichystat předem. Také lze vymyslet redukci na problém nalezení společného +předchůdce vrcholů ve stromě (nebude to \GHT) a použít jedno z~řeÅ¡ení tohoto problému. \h{Konstrukce GHT} -Nyní se nauèíme \GHT{} konstruovat, èím¾ také rozptýlíme obavy o~jejich existenci. -Nejprve v¹ak budeme potøebovat jedno u¾iteèné lemma s~hnusnì technickým dùkazem: +Nyní se naučíme \GHT{} konstruovat, čímž také rozptýlíme obavy o~jejich existenci. +Nejprve vÅ¡ak budeme potřebovat jedno užitečné lemma s~hnusně technickým důkazem: -\s{Hnusnì technické lemma (HTL):} Buïte¾ $s,t$ vrcholy grafu $(V,E)$, $\d(U)$ minimální \st-øez a $u\ne v$ dva rùzné -vrcholy z~$U$. Pak existuje mno¾ina vrcholù $W \subseteq U$ taková, ¾e $\d(W)$ je minimální $uv$-øez. -\foot{To dùle¾ité a netriviální je, ¾e celá $W$ le¾í v~$U$.} +\s{Hnusně technické lemma (HTL):} Buďtež $s,t$ vrcholy grafu $(V,E)$, $\d(U)$ minimální \st-řez a $u\ne v$ dva různé +vrcholy z~$U$. Pak existuje množina vrcholů $W \subseteq U$ taková, že $\d(W)$ je minimální $uv$-řez. +\foot{To důležité a netriviální je, že celá $W$ leží v~$U$.} \fig{4-ght-htl.eps}{\epsfxsize} -\proof Nech» je $\d(X)$ minimální $uv$-øez. -BÚNO mù¾eme pøedpokládat, ¾e $s\in U$ a $t\not\in U$, $u\in X$ a $v\not\in X$ a $s\in X$. -Pokud by tomu tak nebylo, mù¾eme vrcholy pøeznaèit nebo nìkterou z~mno¾in nahradit jejím doplòkem. +\proof NechÅ¥ je $\d(X)$ minimální $uv$-řez. +BÚNO můžeme předpokládat, že $s\in U$ a $t\not\in U$, $u\in X$ a $v\not\in X$ a $s\in X$. +Pokud by tomu tak nebylo, můžeme vrcholy přeznačit nebo některou z~množin nahradit jejím doplňkem. \checkroom{40pt} -Nyní mohou nastat následující dva pøípady:\numlist\nalpha +Nyní mohou nastat následující dva případy:\numlist\nalpha \vbox to 0pt{\vskip 10pt\rightline{\epsfysize=2.5cm\epsfbox{4-ght-htl-a.eps}}\vss}\vskip-\baselineskip -\:$t\not\in X$. Tehdy si v¹imneme, ¾e platí: +\:$t\not\in X$. Tehdy si vÅ¡imneme, že platí: \hangindent=-14em\hangafter=-100 $$\eqalignno{ d(U \cup X) &\ge d(U),&(1) \cr d(U \cap X) + d(U \cup X) &\le d(U) + d(X)&(2)}$$ -První nerovnost plyne z toho, ¾e $\d(U \cup X)$ je nìjaký \st-øez, zatímco $\d(U)$ je minimální \st-øez. -Druhou doká¾eme rozborem pøípadù. - -Mno¾inu vrcholù si disjunktnì rozdìlíme na $X\setminus U$, $X \cap U$, $U \setminus X$ a $\$. -Ka¾dý z~øezù vystupujících v~nerovnosti $(2)$ mù¾eme zapsat jako sjednocení hran mezi nìkterými -z~tìchto skupin vrcholù. -Vytvoøíme tedy tabulku hran mezi ètyømi oznaèenými skupinami vrcholù a ka¾dému -øezu z~$(2)$ oznaèíme jemu odpovídající hrany. Proto¾e je graf neorientovaný, -staèí nám jen horní trojúhelník tabulky. -Pro pøehlednosti si oznaèíme $L_1=\d(U \cap X), L_2=\d(U \cup X), P_1=\d(U)$ a $P_2=\d(X)$. -$$\matrix{&X\setminus U&X \cap U&U \setminus X&\\cr\noalign{\smallskip} +První nerovnost plyne z toho, že $\d(U \cup X)$ je nějaký \st-řez, zatímco $\d(U)$ je minimální \st-řez. +Druhou dokážeme rozborem případů. + +Množinu vrcholů si disjunktně rozdělíme na $X\setminus U$, $X \cap U$, $U \setminus X$ a $\$. +Každý z~řezů vystupujících v~nerovnosti $(2)$ můžeme zapsat jako sjednocení hran mezi některými +z~těchto skupin vrcholů. +Vytvoříme tedy tabulku hran mezi čtyřmi označenými skupinami vrcholů a každému +řezu z~$(2)$ označíme jemu odpovídající hrany. Protože je graf neorientovaný, +stačí nám jen horní trojúhelník tabulky. +Pro přehlednosti si označíme $L_1=\d(U \cap X), L_2=\d(U \cup X), P_1=\d(U)$ a $P_2=\d(X)$. +$$\matrix{&X\setminus U&X \cap U&U \setminus X&\\cr\noalign{\smallskip} X\setminus U&\hbox{---}&L_1,P_1&P_1,P_2&L_2,P_2\cr X \cap U&&\hbox{---}&L_1,P_2&L_1,L_2,P_1,P_2\cr U \setminus X&&&\hbox{---}&L_2,P_1\cr -\&&&&\hbox{---}\cr +\&&&&\hbox{---}\cr }$$ -Vidíme, ¾e ke ka¾dé hranì øezu na levé stranì nerovnosti máme vpravo její protìj¹ek -a navíc hrany mezi $U\setminus X$ a $X \setminus U$ poèítáme jenom vpravo. Nerovnost -$(2)$ tedy platí. +Vidíme, že ke každé hraně řezu na levé straně nerovnosti máme vpravo její protějÅ¡ek +a navíc hrany mezi $U\setminus X$ a $X \setminus U$ počítáme jenom vpravo. Nerovnost +$(2)$ tedy platí. -Nyní staèí nerovnosti $(2)$ a $(1)$ odeèíst, èím¾ získáme: $$d(U \cap X) \le d(X),$$ -co¾ spolu s~obrázkem dokazuje, ¾e $\d(U \cap X)$ je také minimální $uv$-øez. +Nyní stačí nerovnosti $(2)$ a $(1)$ odečíst, čímž získáme: $$d(U \cap X) \le d(X),$$ +což spolu s~obrázkem dokazuje, že $\d(U \cap X)$ je také minimální $uv$-řez. \vbox to 0pt{\vskip 20pt\rightline{\epsfysize=2.5cm\epsfbox{4-ght-htl-b.eps}}\vss}\vskip-\baselineskip -\:$t\in X$. Postupovat budeme obdobnì jako v~pøedchozím pøípadì. Tentokrát se budou +\:$t\in X$. Postupovat budeme obdobně jako v~předchozím případě. Tentokrát se budou hodit tyto nerovnosti: \hangindent=-14em\hangafter=-100 $$\eqalignno{d(X \setminus U) &\ge d(U)&(3)\cr d(U \setminus X) + d(X \setminus U) &\le d(U) + d(X)&(4)}$$ -První platí proto, ¾e $\d(X \setminus U)$ je nìjaký \st-øez, zatímco $\d(U)$ je minimální \st-øez, druhou -doká¾eme opìt dùkladným rozborem pøípadù. +První platí proto, že $\d(X \setminus U)$ je nějaký \st-řez, zatímco $\d(U)$ je minimální \st-řez, druhou +dokážeme opět důkladným rozborem případů. -Oznaème $L_1=\d(U \setminus X), L_2=\d(X \setminus U), P_1=\d(U)$ a $P_2=\d(X)$ a vytvoøme tabulku: -$$\matrix{&X\setminus U&X \cap U&U \setminus X&\\cr\noalign{\smallskip} +Označme $L_1=\d(U \setminus X), L_2=\d(X \setminus U), P_1=\d(U)$ a $P_2=\d(X)$ a vytvořme tabulku: +$$\matrix{&X\setminus U&X \cap U&U \setminus X&\\cr\noalign{\smallskip} X\setminus U&\hbox{---}&L_2,P_1&L_1,L_2,P_1,P_2&L_2,P_2\cr X \cap U&&\hbox{---}&L_1,P_2&P_1,P_2\cr U \setminus X&&&\hbox{---}&L_1,P_1\cr -\&&&&\hbox{---}\cr +\&&&&\hbox{---}\cr }$$ -Stejnì jako v~pøedchozím pøípadì nerovnost $(4)$ platí. Odeètením $(4)$ a $(3)$ získáme: +Stejně jako v~předchozím případě nerovnost $(4)$ platí. Odečtením $(4)$ a $(3)$ získáme: $$d(U \setminus X) \le d(X),$$ -z~èeho¾ opìt dostaneme, ¾e $\d(U \setminus X)$ je také minimální $uv$-øez. +z~čehož opět dostaneme, že $\d(U \setminus X)$ je také minimální $uv$-řez. \qeditem \endlist \bigskip -\>Nyní se koneènì dostáváme ke konstrukci \GHT{}. Abychom mohli pou¾ívat -indukci, zavedeme si trochu obecnìj¹í \GHT{}. - -\s{Definice:} Mìjme neorientovaný graf $(V,E)$. {\I Èásteèný Gomory-Hu Tree} (alias \PGHT{}) pro podmno¾inu vrcholù $R \subseteq V$ je dvojice $((R,F),C)$, -kde $(R,F)$ je strom a mno¾ina $C=\{C(r) \;\vert\; r\in R\}$ je rozklad mno¾iny vrcholù $V$. Tento rozklad -nám øíká, k~jakým vrcholùm \PGHT{} máme pøilepit které vrcholy pùvodního grafu. -Navíc musí platit, ¾e:\numlist\ndotted -\:$\forall r: r\in C(r)$, neboli ka¾dý vrchol \PGHT{} je pøilepen sám k~sobì, a +\>Nyní se konečně dostáváme ke konstrukci \GHT{}. Abychom mohli používat +indukci, zavedeme si trochu obecnější \GHT{}. + +\s{Definice:} Mějme neorientovaný graf $(V,E)$. {\I Částečný Gomory-Hu Tree} (alias \PGHT{}) pro podmnožinu vrcholů $R \subseteq V$ je dvojice $((R,F),C)$, +kde $(R,F)$ je strom a množina $C=\{C(r) \;\vert\; r\in R\}$ je rozklad množiny vrcholů $V$. Tento rozklad +nám říká, k~jakým vrcholům \PGHT{} máme přilepit které vrcholy původního grafu. +Navíc musí platit, že:\numlist\ndotted +\:$\forall r: r\in C(r)$, neboli každý vrchol \PGHT{} je přilepen sám k~sobě, a \:$\forall st \in F: \d\left(\bigcup_{r\in K_1} C(r)\right)=\d\left(\bigcup_{r\in K_2} C(r)\right)$ -je minimální \st-øez, kde $K_1$ a $K_2$ jsou komponenty $(R,F) \setminus st$. +je minimální \st-řez, kde $K_1$ a $K_2$ jsou komponenty $(R,F) \setminus st$. \endlist -\s{Vìta (o~existenci \PGHT{}):} Buï $(V,E)$ neorientovaný nezápornì ohodnocený graf. Pro ka¾dou podmno¾inu vrcholù $R$ +\s{Věta (o~existenci \PGHT{}):} Buď $(V,E)$ neorientovaný nezáporně ohodnocený graf. Pro každou podmnožinu vrcholů $R$ existuje \PGHT{}. -\proof Doká¾eme indukcí podle velikosti mno¾iny $R$.\itemize\ibull -\:$\vert R \vert = 1$: \PGHT{} má jediný vrchol $r\in R$ a $C(r)=V$. -\:$\vert R \vert > 1$: Najdeme dvojici vrcholù $s,t\in R$ takovou, ¾e jejich minimální \st-øez $\d(W)$ -je nejmen¹í mo¾ný. Nyní vytvoøíme graf $G_1$ z~grafu $G$ kontrahováním -v¹ech vrcholù mno¾iny~$W$ do~jednoho vrcholu, který oznaèíme~$v_1$, a vytvoøíme graf $G_2$ z~$G$ kontrahováním -v¹ech vrcholù z~$\overline W$ do jednoho vrcholu $v_2$.\foot{ -Proè to dìláme \uv{tak slo¾itì} a pøidáváme do $G_1$ vrchol $v_1$? Na první pohled to pøeci vypadá zbyteènì. -Problém je v~tom, ¾e i kdy¾ dle HTL le¾í v¹echny minimální øezy oddìlující vrcholy z~$W$ v~mno¾inì vrcholù -$W$, \ tìchto øezù celé v~podgrafu indukovaném~$W$ le¾et nemusí. K~tìmto øezùm toti¾ patøí i hrany, které -mají ve $W$ jenom jeden konec. Proto jsme do $G_1$ pøidali $v_1$ -- do~nìj vedou v¹echny zajímavé -hrany, které mají ve $W$ jeden konec. Tím {\I zajímavé} myslíme to, ¾e z~ka¾dého vrcholu $w\in W$ vede -do $v_1$ \ hrana, která z~nìj vedla do mno¾iny $V\setminus W$, pøípadnì ¾ádná, pokud -do této mno¾iny ¾ádná hrana nevedla.} +\proof Dokážeme indukcí podle velikosti množiny $R$.\itemize\ibull +\:$\vert R \vert = 1$: \PGHT{} má jediný vrchol $r\in R$ a $C(r)=V$. +\:$\vert R \vert > 1$: Najdeme dvojici vrcholů $s,t\in R$ takovou, že jejich minimální \st-řez $\d(W)$ +je nejmenší možný. Nyní vytvoříme graf $G_1$ z~grafu $G$ kontrahováním +vÅ¡ech vrcholů množiny~$W$ do~jednoho vrcholu, který označíme~$v_1$, a vytvoříme graf $G_2$ z~$G$ kontrahováním +vÅ¡ech vrcholů z~$\overline W$ do jednoho vrcholu $v_2$.\foot{ +Proč to děláme \uv{tak složitě} a přidáváme do $G_1$ vrchol $v_1$? Na první pohled to přeci vypadá zbytečně. +Problém je v~tom, že i když dle HTL leží vÅ¡echny minimální řezy oddělující vrcholy z~$W$ v~množině vrcholů +$W$, \ těchto řezů celé v~podgrafu indukovaném~$W$ ležet nemusí. K~těmto řezům totiž patří i hrany, které +mají ve $W$ jenom jeden konec. Proto jsme do $G_1$ přidali $v_1$ -- do~něj vedou vÅ¡echny zajímavé +hrany, které mají ve $W$ jeden konec. Tím {\I zajímavé} myslíme to, že z~každého vrcholu $w\in W$ vede +do $v_1$ \ hrana, která z~něj vedla do množiny $V\setminus W$, případně žádná, pokud +do této množiny žádná hrana nevedla.} \fig{4-ght-g1g2-before.eps}{0.45\hsize} \fig{4-ght-g1g2-after.eps}{0.9\hsize} \finalfix{\bigskip} -Dále vytvoøíme mno¾iny vrcholù $R_1=R \cap \overline W$ a $R_2=R \cap W$. Dle indukèního -pøedpokladu ($R_1$ i $R_2$ jsou men¹í ne¾ $R$) existuje \PGHT{} $T_1=((R_1,F_1),C_1)$ +Dále vytvoříme množiny vrcholů $R_1=R \cap \overline W$ a $R_2=R \cap W$. Dle indukčního +předpokladu ($R_1$ i $R_2$ jsou menší než $R$) existuje \PGHT{} $T_1=((R_1,F_1),C_1)$ pro $R_1$ na $G_1$ a $T_2=((R_2,F_2),C_2)$ pro $R_2$ na $G_2$. -Nyní vytvoøíme \PGHT{} pro pùvodní graf. Oznaème $r_1$ ten vrchol $R_1$, pro který je $v_1 \in C_1(r_1)$, -a~obdobnì $r_2$. Oba \PGHT{} $T_1$ a $T_2$ spojíme hranou $r_1r_2$, tak¾e \PGHT{} pro $G$ -bude $T=((R_1 \cup R_2,F_1 \cup F_2 \cup {r_1r_2}),C)$. Tøídy rozkladu~$C$ zvolíme tak, ¾e pro $r\in R_1$ bude $C(r)=C_1(r)\setminus\{v_1\}$ +Nyní vytvoříme \PGHT{} pro původní graf. Označme $r_1$ ten vrchol $R_1$, pro který je $v_1 \in C_1(r_1)$, +a~obdobně $r_2$. Oba \PGHT{} $T_1$ a $T_2$ spojíme hranou $r_1r_2$, takže \PGHT{} pro $G$ +bude $T=((R_1 \cup R_2,F_1 \cup F_2 \cup {r_1r_2}),C)$. Třídy rozkladu~$C$ zvolíme tak, že pro $r\in R_1$ bude $C(r)=C_1(r)\setminus\{v_1\}$ a pro $r\in R_2$ bude $C(r)=C_2(r)\setminus\{v_2\}$ [odebrali jsme vrcholy $v_1$ a $v_2$ z~rozkladu~$C$]. -Chceme ukázat, ¾e tento $T$ je opravdu \PGHT. $C$ je urèitì rozklad v¹ech vrcholù a ka¾dé -$r\in C(r)$ z~indukèního pøedpokladu, tak¾e podmínka~1 je splnìna. Co se týèe podmínky~2, tak: +Chceme ukázat, že tento $T$ je opravdu \PGHT. $C$ je určitě rozklad vÅ¡ech vrcholů a každé +$r\in C(r)$ z~indukčního předpokladu, takže podmínka~1 je splněna. Co se týče podmínky~2, tak: \itemize\ibull -\:pro hranu \rr\ je $\d(W)$ urèitì minimální \rr-øez, proto¾e øez mezi $s$ a $t$ je souèasnì -i \rr-øezem a je ze v¹ech mo¾ných minimálních øezù na $R$ nejmen¹í, -\:pro hranu $e\ne r_1r_2$ je $\d(e)$ z~indukce minimální øez na jednom z~grafù $G_1$, $G_2$. -Tento øez také pøesnì odpovídá øezu v~grafu~$G$, proto¾e v~$G_1$ i v~$G_2$ jsme poèítali -s~hranami vedoucími do~$v_1$, $v_2$ a proto¾e jsme \PGHT{} napojili pøes vrcholy, -k~nim¾ byly $v_1$ a $v_2$ pøilepeny. - -HTL nám navíc øíká, ¾e existuje minimální øez, který ¾ije pouze v~pøíslu¹ném z~grafù $G_1$, $G_2$, -tak¾e nalezený øez je minimální pro celý graf $G$. +\:pro hranu \rr\ je $\d(W)$ určitě minimální \rr-řez, protože řez mezi $s$ a $t$ je současně +i \rr-řezem a je ze vÅ¡ech možných minimálních řezů na $R$ nejmenší, +\:pro hranu $e\ne r_1r_2$ je $\d(e)$ z~indukce minimální řez na jednom z~grafů $G_1$, $G_2$. +Tento řez také přesně odpovídá řezu v~grafu~$G$, protože v~$G_1$ i v~$G_2$ jsme počítali +s~hranami vedoucími do~$v_1$, $v_2$ a protože jsme \PGHT{} napojili přes vrcholy, +k~nimž byly $v_1$ a $v_2$ přilepeny. + +HTL nám navíc říká, že existuje minimální řez, který žije pouze v~přísluÅ¡ném z~grafů $G_1$, $G_2$, +takže nalezený řez je minimální pro celý graf $G$. \qeditem \endlist \endlist -Nyní víme, ¾e \GHT{} existují, a také víme, jak by se daly konstruovat. Nicménì nalezení -vrcholù $s,t$ tak, aby byl minimální \st-øez nejmen¹í mo¾ný, je èasovì nároèné. -Proto si poslední vìtu je¹tì o~nìco vylep¹íme. +Nyní víme, že \GHT{} existují, a také víme, jak by se daly konstruovat. Nicméně nalezení +vrcholů $s,t$ tak, aby byl minimální \st-řez nejmenší možný, je časově náročné. +Proto si poslední větu jeÅ¡tě o~něco vylepšíme. -\s{Vylep¹ení vìty o~existenci \PGHT{}:} Na zaèátku dùkazu není nutné hledat vrcholy $s$~a~$t$ -takové, aby byl minimální \st-øez nejmen¹í mo¾ný. Staèí zvolit \ vrcholy $s,t\in R$ -a zvolit $\d(W)$ jako minimální \st-øez. +\s{VylepÅ¡ení věty o~existenci \PGHT{}:} Na začátku důkazu není nutné hledat vrcholy $s$~a~$t$ +takové, aby byl minimální \st-řez nejmenší možný. Stačí zvolit \ vrcholy $s,t\in R$ +a zvolit $\d(W)$ jako minimální \st-řez. -\proof Nejprve si uvìdomme, proè jsme v~pøedchozím dùkazu potøebovali, aby byl $\d(W)$ nejmen¹í ze v¹ech -mo¾ných \st-øezù. Bylo to jenom proto, ¾e jsme jím v~\PGHT{} nakonec separovali vrcholy $r_1$ a $r_2$ -a potøebovali jsme záruku, aby byl $\d(W)$ opravdu minimální \rr-øez. Nyní musíme ukázat, -¾e námi nalezený \st-øez $\d(W)$ je také minimálním \rr-øezem. +\proof Nejprve si uvědomme, proč jsme v~předchozím důkazu potřebovali, aby byl $\d(W)$ nejmenší ze vÅ¡ech +možných \st-řezů. Bylo to jenom proto, že jsme jím v~\PGHT{} nakonec separovali vrcholy $r_1$ a $r_2$ +a potřebovali jsme záruku, aby byl $\d(W)$ opravdu minimální \rr-řez. Nyní musíme ukázat, +že námi nalezený \st-řez $\d(W)$ je také minimálním \rr-řezem. -Pro spor tedy pøedpokládejme, ¾e nìjaký \rr-øez $\d(X)$ má men¹í kapacitu ne¾ $\d(W)$. -Navíc vezmìme ten pøípad, kdy se to stalo \uv{poprvé}, tak¾e pro ka¾dé men¹í $R$ je -v¹echno v~poøádku (to mù¾eme, proto¾e pro $\vert R \vert=1$ v¹echno v~poøádku bylo). +Pro spor tedy předpokládejme, že nějaký \rr-řez $\d(X)$ má menší kapacitu než $\d(W)$. +Navíc vezměme ten případ, kdy se to stalo \uv{poprvé}, takže pro každé menší $R$ je +vÅ¡echno v~pořádku (to můžeme, protože pro $\vert R \vert=1$ vÅ¡echno v~pořádku bylo). -Proto¾e $\d(W)$ je minimální \st-øez a $\d(X)$ má men¹í kapacitu, $\d(X)$ nemù¾e separovat -$s$ a $t$. Pøitom ale separuje $r_1$ a $r_2$, tak¾e musí separovat buï $s$ a $r_1$, nebo $t$ a $r_2$. -BÚNO nech» $X$ separuje $s$ a $r_1$. +Protože $\d(W)$ je minimální \st-řez a $\d(X)$ má menší kapacitu, $\d(X)$ nemůže separovat +$s$ a $t$. Přitom ale separuje $r_1$ a $r_2$, takže musí separovat buď $s$ a $r_1$, nebo $t$ a $r_2$. +BÚNO nechÅ¥ $X$ separuje $s$ a $r_1$. \fig{4-ght-rezx.eps}{12cm} -Podívejme se nyní na \PGHT{} $T_1$ (víme, ¾e ten je korektní) a naleznìme v~nìm nejlevnìj¹í hranu $e$ na cestì spojující $s$ a $r_1$. -Tato hrana definuje øez $\d(U)$, co¾ je minimální $sr_1$-øez, podle HTL i v~celém~$G$. Proto¾e $\d(X)$ je $sr_1$-øez, -je $d(U) \le d(X) < d(W)$. Teï si staèí uvìdomit, ¾e $v_1\in C(r_1)$, tak¾e $\d(U)$ -separuje nejenom $s$ a $r_1$, ale také $s$ a $v_1$. Tím pádem ale separuje také $s$ a $t$. -To je spor, proto¾e $d(U) < d(W)$, a pøitom $\d(W)$ mìl být minimální. +Podívejme se nyní na \PGHT{} $T_1$ (víme, že ten je korektní) a nalezněme v~něm nejlevnější hranu $e$ na cestě spojující $s$ a $r_1$. +Tato hrana definuje řez $\d(U)$, což je minimální $sr_1$-řez, podle HTL i v~celém~$G$. Protože $\d(X)$ je $sr_1$-řez, +je $d(U) \le d(X) < d(W)$. Teď si stačí uvědomit, že $v_1\in C(r_1)$, takže $\d(U)$ +separuje nejenom $s$ a $r_1$, ale také $s$ a $v_1$. Tím pádem ale separuje také $s$ a $t$. +To je spor, protože $d(U) < d(W)$, a přitom $\d(W)$ měl být minimální. \qed -Teï u¾ doká¾eme \GHT{} konstruovat efektivnì -- v~ka¾dém kroku vybereme dva vrcholy $s$ a $t$, -nalezneme v~èase $\O(\tau)$ minimální \st-øez a výsledné komponenty s~pøidanými $v_1,v_2$ -zpracujeme rekurzivnì. Celou výstavbu tedy zvládneme v~èase $\O(n\tau)$, èili $\O(n^{5/3}m)$ -pro neohodnocené grafy. +Teď už dokážeme \GHT{} konstruovat efektivně -- v~každém kroku vybereme dva vrcholy $s$ a $t$, +nalezneme v~čase $\O(\tau)$ minimální \st-řez a výsledné komponenty s~přidanými $v_1,v_2$ +zpracujeme rekurzivně. Celou výstavbu tedy zvládneme v~čase $\O(n\tau)$, čili $\O(n^{5/3}m)$ +pro neohodnocené grafy. \references \bye diff --git a/5-mst/5-mst.tex b/5-mst/5-mst.tex index fc83c80..8e580ef 100644 --- a/5-mst/5-mst.tex +++ b/5-mst/5-mst.tex @@ -1,242 +1,242 @@ \input ../sgr.tex -\prednaska{5}{Minimální kostry}{} +\prednaska{5}{Minimální kostry}{} \def\Tmin{T_{min}} -\>Tato kapitola uvede problém minimální kostry, základní vìty o~kostrách a klasické -algoritmy na~hledání minimálních koster. Budeme se inspirovat Tarjanovým pøístupem -z~knihy~\cite{tarjan:dsna}. V¹echny grafy v~této kapitole budou neorientované multigrafy +\>Tato kapitola uvede problém minimální kostry, základní věty o~kostrách a klasické +algoritmy na~hledání minimálních koster. Budeme se inspirovat Tarjanovým přístupem +z~knihy~\cite{tarjan:dsna}. VÅ¡echny grafy v~této kapitole budou neorientované multigrafy a jejich hrany budou ohodnoceny vahami $w: E \to {\bb R}$. -\h{Minimální kostry a jejich vlastnosti} +\h{Minimální kostry a jejich vlastnosti} \s{Definice:} \itemize\ibull -\:{\I Podgrafem} budeme v~této kapitole mínit libovolnou podmno¾inu hran, vrcholy -v¾dy zùstanou zachovány. -\:{\I Pøidání a odebrání hrany} budeme znaèit $T+e:=T\cup \{e\}$, $T-e:=T\setminus \{e\}$. -\:{\I Kostra} (Spanning Tree) souvislého grafu $G$ je libovolný jeho podgraf, který je strom. -Kostru nesouvislého grafu definujeme jako sjednocení koster jednotlivých komponent. -[Alternativnì: kostra je minimální podgraf, který má komponenty s~tými¾ vrcholy +\:{\I Podgrafem} budeme v~této kapitole mínit libovolnou podmnožinu hran, vrcholy +vždy zůstanou zachovány. +\:{\I Přidání a odebrání hrany} budeme značit $T+e:=T\cup \{e\}$, $T-e:=T\setminus \{e\}$. +\:{\I Kostra} (Spanning Tree) souvislého grafu $G$ je libovolný jeho podgraf, který je strom. +Kostru nesouvislého grafu definujeme jako sjednocení koster jednotlivých komponent. +[Alternativně: kostra je minimální podgraf, který má komponenty s~týmiž vrcholy jako komponenty~$G$.] -\:{\I Váha} podgrafu $F\subseteq E$ je $w(F) := \sum_{e\in F} w(e)$. -\:{\I Minimální kostra} (Minimum Spanning Tree, mezi pøáteli té¾ MST) budeme øíkat -ka¾dé kostøe, její¾ váha je mezi v¹emi kostrami daného grafu minimální. +\:{\I Váha} podgrafu $F\subseteq E$ je $w(F) := \sum_{e\in F} w(e)$. +\:{\I Minimální kostra} (Minimum Spanning Tree, mezi přáteli též MST) budeme říkat +každé kostře, jejíž váha je mezi vÅ¡emi kostrami daného grafu minimální. \endlist -Toto je sice standardní definice MST, ale jinak je dosti ne¹ikovná, proto¾e vy¾aduje, -aby bylo váhy mo¾né sèítat. Uká¾eme, ¾e to není potøeba. +Toto je sice standardní definice MST, ale jinak je dosti neÅ¡ikovná, protože vyžaduje, +aby bylo váhy možné sčítat. Ukážeme, že to není potřeba. \s{Definice:} -Buï $T \subseteq G$ nìjaká kostra grafu~$G$. Pak: +Buď $T \subseteq G$ nějaká kostra grafu~$G$. Pak: \itemize\ibull -\:$T[x,y]$ bude znaèit cestu v~$T$, která spojuje $x$ a $y$. (Cestou opìt míníme mno¾inu hran.) -\:$T[e]:=T[x,y]$ pro hranu $e=xy$. Této cestì budeme øíkat {\I cesta pokrytá hranou~$e$.} -\:Hrana $e\in E \setminus T$ je {\I lehká vzhledem k~$T$} $\equiv \exists e^\prime \in T[e]: w(e)(T,e,e^\prime) := T-e+e'$. +zaveďme $\(T,e,e^\prime) := T-e+e'$. -\s{Pozorování:} -Pokud $e^\prime \not\in T$ a $e\in T[e^\prime]$, je $\(T,e,e^\prime)$ opìt kostra. -Staèí si uvìdomit, ¾e pøidáním $e^\prime$ do~$T$ vznikne kru¾nice (konkrétnì $T[e^\prime] + e^\prime$) -a vynecháním libovolné hrany z~této kru¾nice získáme opìt kostru. +\s{Pozorování:} +Pokud $e^\prime \not\in T$ a $e\in T[e^\prime]$, je $\(T,e,e^\prime)$ opět kostra. +Stačí si uvědomit, že přidáním $e^\prime$ do~$T$ vznikne kružnice (konkrétně $T[e^\prime] + e^\prime$) +a vynecháním libovolné hrany z~této kružnice získáme opět kostru. -\figure{mst2.eps}{Kostra $T$, cesta $T[e]$ a výsledek operace $\(T,e',e)$}{\epsfxsize} +\figure{mst2.eps}{Kostra $T$, cesta $T[e]$ a výsledek operace $\(T,e',e)$}{\epsfxsize} -\figure{mst1.eps}{Jeden krok dùkazu swapovacího lemmatu}{\epsfxsize} +\figure{mst1.eps}{Jeden krok důkazu swapovacího lemmatu}{\epsfxsize} -\s{Lemma o~swapování:} -Máme-li libovolné kostry $T$ a $T'$, pak lze z~$T$ dostat $T'$ koneèným poètem operací \. +\s{Lemma o~swapování:} +Máme-li libovolné kostry $T$ a $T'$, pak lze z~$T$ dostat $T'$ konečným počtem operací \. \proof -Pokud $T \ne T'$, musí existovat hrana $e' \in T'\setminus T$, proto¾e $\vert T \vert = \vert T' \vert$. -Kru¾nice $T[e']+e'$ nemù¾e být celá obsa¾ena v~$T'$, tak¾e existuje hrana +Pokud $T \ne T'$, musí existovat hrana $e' \in T'\setminus T$, protože $\vert T \vert = \vert T' \vert$. +Kružnice $T[e']+e'$ nemůže být celá obsažena v~$T'$, takže existuje hrana $e\in T[e']\setminus T'$ a $\check{T} := \(T,e,e')$ je kostra, pro kterou $\vert \check{T} \symdiff T' \vert = \vert T \symdiff T' \vert -2$. -Po~koneèném poètu tìchto krokù tedy musíme dojít k~$T'$. +Po~konečném počtu těchto kroků tedy musíme dojít k~$T'$. \qed -\s{Monotónní lemma o~swapování:} -Je-li $T$ kostra, k~ní¾ neexistují ¾ádné lehké hrany, a~$T'$ libovolná kostra, -pak lze od~$T$ k~$T'$ pøejít posloupností swapù, pøi které váha kostry neklesá. +\s{Monotónní lemma o~swapování:} +Je-li $T$ kostra, k~níž neexistují žádné lehké hrany, a~$T'$ libovolná kostra, +pak lze od~$T$ k~$T'$ přejít posloupností swapů, při které váha kostry neklesá. \proof -Podobnì jako u~pøedchozího lemmatu budeme postupovat indukcí podle $\vert T \symdiff T' \vert$. -Pokud zvolíme libovolnì hranu $e'\in T'\setminus T$ a k~ní $e\in T[e']\setminus T'$, musí -$\check{T}:=\(T,e,e')$ být kostra bli¾¹í k~$T'$ a $w(\check{T})\ge w(T)$, -jeliko¾ $e'$ nemù¾e být lehká vzhledem k~$T$, tak¾e speciálnì $w(e')\ge w(e)$. - -Aby mohla indukce pokraèovat, potøebujeme je¹tì dokázat, ¾e ani k~nové kostøe neexistují -lehké hrany v~$T'\setminus \check{T}$. K~tomu nám pomù¾e zvolit si ze~v¹ech mo¾ných hran~$e'$ tu s~nejmen¹í vahou. -Uva¾me nyní hranu~$f\in T'\setminus \check{T}$. -Cesta $\check{T}[f]$ pokrytá touto hranou v~nové kostøe je buïto pùvodní $T[f]$ (to pokud $e\not\in T[f]$) -nebo $T[f] \symdiff C$, kde $C$ je kru¾nice $T[e']+e'$. První pøípad je triviální, -ve~druhém si staèí uvìdomit, ¾e $w(f)\ge w(e')$ a ostatní hrany na~$C$ jsou lehèí -ne¾~$e'$. +Podobně jako u~předchozího lemmatu budeme postupovat indukcí podle $\vert T \symdiff T' \vert$. +Pokud zvolíme libovolně hranu $e'\in T'\setminus T$ a k~ní $e\in T[e']\setminus T'$, musí +$\check{T}:=\(T,e,e')$ být kostra bližší k~$T'$ a $w(\check{T})\ge w(T)$, +jelikož $e'$ nemůže být lehká vzhledem k~$T$, takže speciálně $w(e')\ge w(e)$. + +Aby mohla indukce pokračovat, potřebujeme jeÅ¡tě dokázat, že ani k~nové kostře neexistují +lehké hrany v~$T'\setminus \check{T}$. K~tomu nám pomůže zvolit si ze~vÅ¡ech možných hran~$e'$ tu s~nejmenší vahou. +Uvažme nyní hranu~$f\in T'\setminus \check{T}$. +Cesta $\check{T}[f]$ pokrytá touto hranou v~nové kostře je buďto původní $T[f]$ (to pokud $e\not\in T[f]$) +nebo $T[f] \symdiff C$, kde $C$ je kružnice $T[e']+e'$. První případ je triviální, +ve~druhém si stačí uvědomit, že $w(f)\ge w(e')$ a ostatní hrany na~$C$ jsou lehčí +než~$e'$. \qed -\s{Dùkaz vìty:} +\s{Důkaz věty:} \itemize\ibull -\:$\exists$ lehká hrana $\Rightarrow$ $T$ není minimální. +\:$\exists$ lehká hrana $\Rightarrow$ $T$ není minimální. -Nech» $\exists e$ lehká. Najdeme $e' \in T[e] : w(e) < w(e')$ (ta musí existovat z~definice lehké hrany). -Kostra $T' := \(T,e,e')$ je lehèí ne¾~$T$. +NechÅ¥ $\exists e$ lehká. Najdeme $e' \in T[e] : w(e) < w(e')$ (ta musí existovat z~definice lehké hrany). +Kostra $T' := \(T,e,e')$ je lehčí než~$T$. \medskip -\:K~$T$ neexistuje lehká hrana $\Rightarrow$ $T$ je minimální. +\:K~$T$ neexistuje lehká hrana $\Rightarrow$ $T$ je minimální. -Uva¾me nìjakou minimální kostru $\Tmin$ a pou¾ijme monotónní swapovací lemma na~$T$ a $\Tmin$. Z~nìj plyne $w(T)\le w(\Tmin)$, +Uvažme nějakou minimální kostru $\Tmin$ a použijme monotónní swapovací lemma na~$T$ a $\Tmin$. Z~něj plyne $w(T)\le w(\Tmin)$, a~tedy $w(T)=w(\Tmin)$. \qeditem \endlist -\s{Vìta:} -Jsou-li v¹echny váhy hran navzájem rùzné, je MST urèena jednoznaènì. +\s{Věta:} +Jsou-li vÅ¡echny váhy hran navzájem různé, je MST určena jednoznačně. \proof -Máme-li dvì MST $T_1$ a $T_2$, neobsahují podle pøedchozí vìty lehké hrany, tak¾e podle monotónního -lemmatu mezi nimi lze pøeswapovat bez poklesu váhy. Pokud jsou ale váhy rùzné, musí ka¾dé swapnutí -ostøe zvý¹it váhu, a~proto k~¾ádnému nemohlo dojít. +Máme-li dvě MST $T_1$ a $T_2$, neobsahují podle předchozí věty lehké hrany, takže podle monotónního +lemmatu mezi nimi lze přeswapovat bez poklesu váhy. Pokud jsou ale váhy různé, musí každé swapnutí +ostře zvýšit váhu, a~proto k~žádnému nemohlo dojít. \qed -\s{Poznámka:} Èasto se nám bude hodit, aby kostra, kterou hledáme, byla urèena jednoznaènì. -Tehdy mù¾eme vyu¾ít pøedchozí vìty a váhy zmìnit o~vhodné epsilony, respektive kvaziuspoøádání -roz¹íøit na~lineární uspoøádání. +\s{Poznámka:} Často se nám bude hodit, aby kostra, kterou hledáme, byla určena jednoznačně. +Tehdy můžeme využít předchozí věty a váhy změnit o~vhodné epsilony, respektive kvaziuspořádání +rozšířit na~lineární uspořádání. -\h{Èervenomodrý meta-algoritmus} +\h{Červenomodrý meta-algoritmus} -V¹echny tradièní algoritmy na~hledání MST lze popsat jako speciální pøípady následujícího -meta-algoritmu. Rozeberme si tedy rovnou ten. Formulujeme ho pro pøípad, kdy jsou v¹echny -váhy hran navzájem rùzné. +VÅ¡echny tradiční algoritmy na~hledání MST lze popsat jako speciální případy následujícího +meta-algoritmu. Rozeberme si tedy rovnou ten. Formulujeme ho pro případ, kdy jsou vÅ¡echny +váhy hran navzájem různé. \s{Meta-algoritmus:} \algo -\:Na poèátku jsou v¹echny hrany bezbarvé. -\:Dokud to lze, pou¾ijeme jedno z~následujících pravidel: -\::{\I Modré pravidlo:} Vyber øez takový, ¾e jeho nejlehèí hrana není modrá,\foot{Za -touto podmínkou nehledejte ¾ádná kouzla, je tu pouze proto, aby se algoritmus nemohl -zacyklit neustálým provádìním pravidel, která nic nezmìní.} a obarvi ji na~modro. -\::{\I Èervené pravidlo:} Vyber cyklus takový, ¾e jeho nejtì¾¹í hrana není èervená, a obarvi ji na~èerveno. +\:Na počátku jsou vÅ¡echny hrany bezbarvé. +\:Dokud to lze, použijeme jedno z~následujících pravidel: +\::{\I Modré pravidlo:} Vyber řez takový, že jeho nejlehčí hrana není modrá,\foot{Za +touto podmínkou nehledejte žádná kouzla, je tu pouze proto, aby se algoritmus nemohl +zacyklit neustálým prováděním pravidel, která nic nezmění.} a obarvi ji na~modro. +\::{\I Červené pravidlo:} Vyber cyklus takový, že jeho nejtěžší hrana není červená, a obarvi ji na~červeno. \endalgo -\s{Vìta:} -Pro Èervenomodrý meta-algoritmus spu¹tìný na~libovolném grafu s~hranami lineárnì uspoøádanými -podle vah platí: +\s{Věta:} +Pro Červenomodrý meta-algoritmus spuÅ¡těný na~libovolném grafu s~hranami lineárně uspořádanými +podle vah platí: \algo -\:V¾dy se zastaví. -\:Po zastavení jsou v¹echny hrany obarvené. -\:Modøe obarvené hrany tvoøí minimální kostru. +\:Vždy se zastaví. +\:Po zastavení jsou vÅ¡echny hrany obarvené. +\:Modře obarvené hrany tvoří minimální kostru. \endalgo \proof -Nejdøíve si doká¾eme nìkolik lemmat. Jeliko¾ hrany mají navzájem rùzné váhy, -mù¾eme pøedpokládat, ¾e algoritmus má sestrojit jednu konkrétní minimální kostru~$\Tmin$. +Nejdříve si dokážeme několik lemmat. Jelikož hrany mají navzájem různé váhy, +můžeme předpokládat, že algoritmus má sestrojit jednu konkrétní minimální kostru~$\Tmin$. -\s{Modré lemma:} Je-li libovolná hrana~$e$ algoritmem kdykoliv obarvena na~modro, pak $e\in \Tmin$. +\s{Modré lemma:} Je-li libovolná hrana~$e$ algoritmem kdykoliv obarvena na~modro, pak $e\in \Tmin$. -\proof Sporem: Hrana~$e$ byla omodøena jako nejlehèí hrana nìjakého øezu~$C$. -Pokud $e\not\in \Tmin$, musí cesta $\Tmin[e]$ obsahovat nìjakou jinou -hranu~$e'$ øezu~$C$. Jen¾e $e'$ je tì¾¹í ne¾~$e$, tak¾e operací $\(\Tmin,e',e)$ -získáme je¹tì lehèí kostru, co¾ není mo¾né. +\proof Sporem: Hrana~$e$ byla omodřena jako nejlehčí hrana nějakého řezu~$C$. +Pokud $e\not\in \Tmin$, musí cesta $\Tmin[e]$ obsahovat nějakou jinou +hranu~$e'$ řezu~$C$. Jenže $e'$ je těžší než~$e$, takže operací $\(\Tmin,e',e)$ +získáme jeÅ¡tě lehčí kostru, což není možné. \qed -\figure{mst-rb.eps}{Situace v~dùkazu Modrého a Èerveného lemmatu}{\epsfxsize} +\figure{mst-rb.eps}{Situace v~důkazu Modrého a Červeného lemmatu}{\epsfxsize} -\s{Èervené lemma:} Je-li libovolná hrana~$e$ algoritmem kdykoliv obarvena na~èerveno, +\s{Červené lemma:} Je-li libovolná hrana~$e$ algoritmem kdykoliv obarvena na~červeno, pak $e\not\in \Tmin$. -\proof Opìt sporem: Pøedpokládejme, ¾e~$e$ byla obarvena èervenì jako nejtì¾¹í na~nìjaké kru¾nici~$C$ -a ¾e $e\in \Tmin$. Odebráním~$e$ se nám $\Tmin$ rozpadne na~dvì komponenty $T_x$ a $T_y$. -Nìkteré vrcholy kru¾nice pøipadnou do komponenty $T_x$, ostatní do~$T_y$. Na~$C$ ale musí -existovat nìjaká hrana $e'\ne e$, její¾ krajní vrcholy le¾í v~rùzných komponentách, -a~jeliko¾ hrana~$e$ byla na~kru¾nici nejtì¾¹í, je $w(e') < w(e)$. Pomocí $\(\Tmin,e,e')$ -proto získáme lehèí kostru, a~to je spor. +\proof Opět sporem: Předpokládejme, že~$e$ byla obarvena červeně jako nejtěžší na~nějaké kružnici~$C$ +a že $e\in \Tmin$. Odebráním~$e$ se nám $\Tmin$ rozpadne na~dvě komponenty $T_x$ a $T_y$. +Některé vrcholy kružnice připadnou do komponenty $T_x$, ostatní do~$T_y$. Na~$C$ ale musí +existovat nějaká hrana $e'\ne e$, jejíž krajní vrcholy leží v~různých komponentách, +a~jelikož hrana~$e$ byla na~kružnici nejtěžší, je $w(e') < w(e)$. Pomocí $\(\Tmin,e,e')$ +proto získáme lehčí kostru, a~to je spor. \qed -\s{Bezbarvé lemma:} Pokud existuje nìjaká neobarvená hrana, lze je¹tì pou¾ít nìkteré +\s{Bezbarvé lemma:} Pokud existuje nějaká neobarvená hrana, lze jeÅ¡tě použít některé z~pravidel. -\proof Nech» existuje hrana~$e=xy$, která je stále bezbarvá. Oznaèíme si $M$ mno¾inu vrcholù, -do~nich¾ se lze z~$x$ dostat po~modrých hranách. Nyní mohou nastat dvì mo¾nosti: +\proof NechÅ¥ existuje hrana~$e=xy$, která je stále bezbarvá. Označíme si $M$ množinu vrcholů, +do~nichž se lze z~$x$ dostat po~modrých hranách. Nyní mohou nastat dvě možnosti: \itemize\ibull -\:$y \in M$ (tj. existuje modrá cesta z~$x$ do~$y$): Modrá cesta je v~minimální kostøe a k~minimální kostøe -neexistují ¾ádné lehké hrany, tak¾e hrana $e$ je nejdra¾¹í na~cyklu tvoøeném modrou cestou a~touto hranou -a mohu na ni pou¾ít èervené pravidlo. +\:$y \in M$ (tj. existuje modrá cesta z~$x$ do~$y$): Modrá cesta je v~minimální kostře a k~minimální kostře +neexistují žádné lehké hrany, takže hrana $e$ je nejdražší na~cyklu tvořeném modrou cestou a~touto hranou +a mohu na ni použít červené pravidlo. -\figure{mst-bez.eps}{Situace v~dùkazu Bezbarvého lemmatu}{\epsfxsize} +\figure{mst-bez.eps}{Situace v~důkazu Bezbarvého lemmatu}{\epsfxsize} -\:$y \notin M$: Tehdy øez $\delta(M)$ neobsahuje ¾ádné modré hrany, tak¾e na~tento øez -mù¾eme pou¾ít modré pravidlo. +\:$y \notin M$: Tehdy řez $\delta(M)$ neobsahuje žádné modré hrany, takže na~tento řez +můžeme použít modré pravidlo. \qeditem \endlist -\ss{Dùkaz vìty:} +\ss{Důkaz věty:} \itemize\ibull -\:{\I Zastaví se:} Z~èerveného a modrého lemmatu plyne, ¾e ¾ádnou hranu nikdy nepøebarvíme. Ka¾dým krokem pøibude - alespoò jedna obarvená hrana, tak¾e se algoritmus po~nejvý¹e $m$~krocích zastaví. -\:{\I Obarví v¹e:} Pokud existuje alespoò jedna neobarvená hrana, pak podle bezbarvého lemmatu algoritmus pokraèuje. -\:{\I Najde modrou MST:} Podle èerveného a modrého lemmatu le¾í v~$\Tmin$ právì modré hrany. +\:{\I Zastaví se:} Z~červeného a modrého lemmatu plyne, že žádnou hranu nikdy nepřebarvíme. Každým krokem přibude + alespoň jedna obarvená hrana, takže se algoritmus po~nejvýše $m$~krocích zastaví. +\:{\I Obarví vÅ¡e:} Pokud existuje alespoň jedna neobarvená hrana, pak podle bezbarvého lemmatu algoritmus pokračuje. +\:{\I Najde modrou MST:} Podle červeného a modrého lemmatu leží v~$\Tmin$ právě modré hrany. \qeditem \endlist -\s{Poznámka:} -Èervené a modré pravidlo jsou v~jistém smyslu duální. Pro rovinné grafy je na~sebe pøevede obyèejná rovinná -dualita (staèí si uvìdomit, ¾e kostra duálního grafu je komplement duálu kostry primárního grafu), obecnìji -je to dualita mezi matroidy, která prohazuje øezy a cykly. +\s{Poznámka:} +Červené a modré pravidlo jsou v~jistém smyslu duální. Pro rovinné grafy je na~sebe převede obyčejná rovinná +dualita (stačí si uvědomit, že kostra duálního grafu je komplement duálu kostry primárního grafu), obecněji +je to dualita mezi matroidy, která prohazuje řezy a cykly. -\h{Klasické algoritmy na hledání MST} +\h{Klasické algoritmy na hledání MST} -\ss{Kruskalùv neboli Hladový:\foot{\rm Mo¾ná hladový s~malým `h', ale tento algoritmus je pradìdeèkem -v¹ech ostatních hladových algoritmù, tak mu tu èest pøejme.}} +\ss{Kruskalův neboli Hladový:\foot{\rm Možná hladový s~malým `h', ale tento algoritmus je pradědečkem +vÅ¡ech ostatních hladových algoritmů, tak mu tu čest přejme.}} \algo -\:Setøídíme hrany podle vah vzestupnì. -\:Zaèneme s~prázdnou kostrou (ka¾dý vrchol je v~samostatné komponentì souvislosti). -\:Bereme hrany ve vzestupném poøadí. -\::Pro ka¾dou hranu $e$ se podíváme, zda spojuje dvì rùzné komponenty -- pokud ano, pøidáme ji do~kostry, - jinak ji zahodíme. +\:Setřídíme hrany podle vah vzestupně. +\:Začneme s~prázdnou kostrou (každý vrchol je v~samostatné komponentě souvislosti). +\:Bereme hrany ve vzestupném pořadí. +\::Pro každou hranu $e$ se podíváme, zda spojuje dvě různé komponenty -- pokud ano, přidáme ji do~kostry, + jinak ji zahodíme. \endalgo -Èervenomodrý pohled: pìstujeme modrý les. Pokud hrana spojuje dva stromeèky, je~urèitì minimální v~øezu mezi -jedním ze~stromeèkù a zbytkem grafu (ostatní hrany tého¾ øezu jsme je¹tì nezpracovali). Pokud nespojuje, -je maximální na~nìjakém cyklu tvoøeném touto hranou a nìjakými døíve pøidanými. +Červenomodrý pohled: pěstujeme modrý les. Pokud hrana spojuje dva stromečky, je~určitě minimální v~řezu mezi +jedním ze~stromečků a zbytkem grafu (ostatní hrany téhož řezu jsme jeÅ¡tě nezpracovali). Pokud nespojuje, +je maximální na~nějakém cyklu tvořeném touto hranou a nějakými dříve přidanými. -Potøebujeme èas $\O(m \log n)$ na~setøídìní hran a dále datovou strukturu pro udr¾ování komponent souvislosti -(Union-Find Problem), se~kterou provedeme $m$~operací \ a $n$ operací \. Nejlep¹í známá implementace -této struktury dává slo¾itost obou operací $\O(\alpha(n))$ amortizovanì, tak¾e celkovì hladový algoritmus -dobìhne v~èase $\O(m \log n + m \alpha(n))$. +Potřebujeme čas $\O(m \log n)$ na~setřídění hran a dále datovou strukturu pro udržování komponent souvislosti +(Union-Find Problem), se~kterou provedeme $m$~operací \ a $n$ operací \. Nejlepší známá implementace +této struktury dává složitost obou operací $\O(\alpha(n))$ amortizovaně, takže celkově hladový algoritmus +doběhne v~čase $\O(m \log n + m \alpha(n))$. -\ss{Borùvkùv:} +\ss{Borůvkův:} -Opìt si budeme pìstovat modrý les, av¹ak tentokrát jej budeme roz¹iøovat ve~fázích. V~jedné fázi nalezneme ke ka¾dému stromeèku nejlevnìj¹í incidentní hranu -a v¹echny tyto nalezené hrany naráz pøidáme (aplikujeme nìkolik modrých pravidel najednou). Pokud jsou v¹echny váhy rùzné, cyklus -tím nevznikne. +Opět si budeme pěstovat modrý les, avÅ¡ak tentokrát jej budeme rozÅ¡iřovat ve~fázích. V~jedné fázi nalezneme ke každému stromečku nejlevnější incidentní hranu +a vÅ¡echny tyto nalezené hrany naráz přidáme (aplikujeme několik modrých pravidel najednou). Pokud jsou vÅ¡echny váhy různé, cyklus +tím nevznikne. -Poèet stromeèkù klesá exponenciálnì $\Rightarrow$ fází je celkem $\log n$. Pokud ka¾dou fázi -implementujeme lineárním prùchodem celého grafu, dostaneme slo¾itost $\O(m\log n)$. -Mimo to lze ka¾dou fázi výteènì paralelizovat. +Počet stromečků klesá exponenciálně $\Rightarrow$ fází je celkem $\log n$. Pokud každou fázi +implementujeme lineárním průchodem celého grafu, dostaneme složitost $\O(m\log n)$. +Mimo to lze každou fázi výtečně paralelizovat. -\ss{Jarníkùv:} +\ss{Jarníkův:} -Jarníkùv algoritmus je podobný Borùvkovi, ale s tím rozdílem, ¾e nenecháme rùst celý les, ale jen jeden modrý strom. V~ka¾dém -okam¾iku nalezneme nejlevnìj¹í hranu vedoucí mezi stromem a zbytkem grafu a pøidáme ji ke~stromu (modré pravidlo); -hrany vedoucí uvnitø stromu prùbì¾nì zahazujeme (èervené pravidlo). Kroky opakujeme, dokud se strom nerozroste pøes v¹echny vrcholy. -Pøi ¹ikovné implementaci pomocí haldy dosáhneme èasové slo¾itosti $\O(m\log n)$, v~pøí¹tí kapitole uká¾eme implementaci je¹tì ¹ikovnìj¹í. +Jarníkův algoritmus je podobný Borůvkovi, ale s tím rozdílem, že nenecháme růst celý les, ale jen jeden modrý strom. V~každém +okamžiku nalezneme nejlevnější hranu vedoucí mezi stromem a zbytkem grafu a přidáme ji ke~stromu (modré pravidlo); +hrany vedoucí uvnitř stromu průběžně zahazujeme (červené pravidlo). Kroky opakujeme, dokud se strom nerozroste přes vÅ¡echny vrcholy. +Při Å¡ikovné implementaci pomocí haldy dosáhneme časové složitosti $\O(m\log n)$, v~příští kapitole ukážeme implementaci jeÅ¡tě Å¡ikovnější. -\s{Cvièení:} -Naleznìte jednoduchý algoritmus pro výpoèet MST v~grafech ohodnocených vahami $\{1,\ldots k\}$ se slo¾itostí $\O(mk)$ +\s{Cvičení:} +Nalezněte jednoduchý algoritmus pro výpočet MST v~grafech ohodnocených vahami $\{1,\ldots k\}$ se složitostí $\O(mk)$ nebo dokonce~$\O(m+nk)$. \references diff --git a/6-borjar/6-borjar.tex b/6-borjar/6-borjar.tex index b48e6f6..8d654e5 100644 --- a/6-borjar/6-borjar.tex +++ b/6-borjar/6-borjar.tex @@ -1,264 +1,264 @@ \input ../sgr.tex -\prednaska{6}{Rychlej¹í algoritmy na minimální kostry}{} +\prednaska{6}{Rychlejší algoritmy na minimální kostry}{} -V~této kapitole popí¹eme nìkolik pokroèilej¹ích algoritmù pro problém minimální -kostry. Vesmìs to budou rùzná vylep¹ení klasických algoritmù z~minulé kapitoly. +V~této kapitole popíšeme několik pokročilejších algoritmů pro problém minimální +kostry. Vesměs to budou různá vylepÅ¡ení klasických algoritmů z~minulé kapitoly. -\h{Upravená verze Borùvkova algoritmu pro rovinné grafy} +\h{Upravená verze Borůvkova algoritmu pro rovinné grafy} -Vyjdeme z my¹lenky, ¾e mù¾eme po ka¾dém kroku pùvodního Borùvkova algoritmu vzniklé komponenty -souvislosti grafu kontrahovat do jednoho vrcholu a tím získat men¹í graf, který mù¾eme -znovu rekurzivnì zmen¹ovat. To funguje obecnì, ale uká¾eme, ¾e pro rovinné grafy tak dosáhneme -lineární èasové slo¾itosti. +Vyjdeme z myÅ¡lenky, že můžeme po každém kroku původního Borůvkova algoritmu vzniklé komponenty +souvislosti grafu kontrahovat do jednoho vrcholu a tím získat menší graf, který můžeme +znovu rekurzivně zmenÅ¡ovat. To funguje obecně, ale ukážeme, že pro rovinné grafy tak dosáhneme +lineární časové složitosti. -\s{Pozorování:} -Pokud $F \subseteq {\rm MST}(G)$ (kde ${\rm MST}(G)$ je minimální kostra grafu~$G$), $G'$~je graf vzniklý -z~$G$ kontrakcí podél hran z~$F$, pak kostra grafu~$G$, která vznikne z~${\rm MST}(G')$ zpìtným -expandováním kontrahovaných vrcholù, je ${\rm MST}(G)$. Pokud kontrakcí vzniknou -smyèky, mù¾eme je ihned odstraòovat; pokud paralelní hrany, ponecháme z~nich v¾dy tu nejlehèí. -To nás vede k následujícímu algoritmu: +\s{Pozorování:} +Pokud $F \subseteq {\rm MST}(G)$ (kde ${\rm MST}(G)$ je minimální kostra grafu~$G$), $G'$~je graf vzniklý +z~$G$ kontrakcí podél hran z~$F$, pak kostra grafu~$G$, která vznikne z~${\rm MST}(G')$ zpětným +expandováním kontrahovaných vrcholů, je ${\rm MST}(G)$. Pokud kontrakcí vzniknou +smyčky, můžeme je ihned odstraňovat; pokud paralelní hrany, ponecháme z~nich vždy tu nejlehčí. +To nás vede k následujícímu algoritmu: -\s{Algoritmus: MST v rovinných grafech} \cite{mm:mst} +\s{Algoritmus: MST v rovinných grafech} \cite{mm:mst} \algo -\:Ke ka¾dému vrcholu najdeme nejlevnìj¹í incidentní hranu -- dostaneme mno¾inu hran $F \subseteq E$. -\:Graf kontrahujeme podle $F$ následovnì: -\::Prohledáme do ¹íøky graf $(V, F)$ a pøiøadíme ka¾dému vrcholu èíslo komponenty, v~ní¾ se nachází. -\::Pøeèíslujeme hrany v~$G$ podle èísel komponent. -\:Odstraníme násobné hrany: -\::Setøídíme hrany lexikograficky pøihrádkovým tøídìním (násobné hrany jsou nyní pospolu). -\::Projdeme posloupnost hran a z~ka¾dého úseku multihran odstraníme v¹echny a¾ na nejlevnìj¹í hranu. -Také odstraníme smyèky. -\:Pokud stále máme netriviální graf, opakujeme pøedchozí kroky. -\:Vrátíme jako MST v¹echny hrany, které se v~prùbìhu algoritmu dostaly do~$F$. +\:Ke každému vrcholu najdeme nejlevnější incidentní hranu -- dostaneme množinu hran $F \subseteq E$. +\:Graf kontrahujeme podle $F$ následovně: +\::Prohledáme do šířky graf $(V, F)$ a přiřadíme každému vrcholu číslo komponenty, v~níž se nachází. +\::Přečíslujeme hrany v~$G$ podle čísel komponent. +\:Odstraníme násobné hrany: +\::Setřídíme hrany lexikograficky přihrádkovým tříděním (násobné hrany jsou nyní pospolu). +\::Projdeme posloupnost hran a z~každého úseku multihran odstraníme vÅ¡echny až na nejlevnější hranu. +Také odstraníme smyčky. +\:Pokud stále máme netriviální graf, opakujeme předchozí kroky. +\:Vrátíme jako MST vÅ¡echny hrany, které se v~průběhu algoritmu dostaly do~$F$. \endalgo -\s{Èasová slo¾itost:} -Oznaème si $n_i$ a $m_i$ poèet vrcholù a hran na~poèátku $i$-té iterace. -Ka¾dý z~krokù 1--7 trvá $\O(m_i)$, proto i celý cyklus algoritmu trvá $\O(m_i)$. -Poèet vrcholù grafu klesá s~ka¾dým cyklem exponenciálnì: $n_i \leq n / 2^i$. -Na~zaèátku ka¾dého cyklu je graf rovinný (kontrakcí hrany v~rovinném grafu se rovinnost -zachovává) a není to multigraf, tak¾e poèet jeho hran je lineární v poètu vrcholù: -$m_i < 3n_i$. Celkovou èasovou slo¾itost dostaneme jako souèet dob trvání -v¹ech cyklù: $\O(\sum_i m_i) = \O(\sum_i n_i) = \O(n)$. +\s{Časová složitost:} +Označme si $n_i$ a $m_i$ počet vrcholů a hran na~počátku $i$-té iterace. +Každý z~kroků 1--7 trvá $\O(m_i)$, proto i celý cyklus algoritmu trvá $\O(m_i)$. +Počet vrcholů grafu klesá s~každým cyklem exponenciálně: $n_i \leq n / 2^i$. +Na~začátku každého cyklu je graf rovinný (kontrakcí hrany v~rovinném grafu se rovinnost +zachovává) a není to multigraf, takže počet jeho hran je lineární v počtu vrcholů: +$m_i < 3n_i$. Celkovou časovou složitost dostaneme jako součet dob trvání +vÅ¡ech cyklů: $\O(\sum_i m_i) = \O(\sum_i n_i) = \O(n)$. -\h{Minorovì uzavøené tøídy} +\h{Minorově uzavřené třídy} -Pøedchozí algoritmus ve~skuteènosti funguje v~lineárním èase i pro obecnìj¹í tøídy grafù, -ne¾ jsou grafy rovinné. Tím správným universem jsou minorovì uzavøené tøídy: +Předchozí algoritmus ve~skutečnosti funguje v~lineárním čase i pro obecnější třídy grafů, +než jsou grafy rovinné. Tím správným universem jsou minorově uzavřené třídy: \s{Definice:} -Graf $H$ je {\I minorem} grafu $G$ (znaèíme $H \preceq G$), pokud lze $H$ získat z~$G$ -mazáním vrcholù èi hran a kontrahováním hran (s~odstranìním smyèek a násobných hran). +Graf $H$ je {\I minorem} grafu $G$ (značíme $H \preceq G$), pokud lze $H$ získat z~$G$ +mazáním vrcholů či hran a kontrahováním hran (s~odstraněním smyček a násobných hran). -\s{Pozorování:} -Relace $\preceq$ je èásteèné uspoøádání na tøídì v¹ech grafù -(reflexivita a tranzitivita plynou pøímo z~definice, pro antisymetrii si staèí -v¹imnout, ¾e jak mazáním, tak kontrakcemi klesá souèet poètu vrcholù s~poètem hran). +\s{Pozorování:} +Relace $\preceq$ je částečné uspořádání na třídě vÅ¡ech grafů +(reflexivita a tranzitivita plynou přímo z~definice, pro antisymetrii si stačí +vÅ¡imnout, že jak mazáním, tak kontrakcemi klesá součet počtu vrcholů s~počtem hran). -\s{Pozorování:} -Pokud je graf~$H$ podgrafem grafu~$G$, pak je také jeho minorem. -Opaènì to neplatí: napøíklad $C_3$ je minorem libovolné del¹í kru¾nice, -ale urèitì ne jejím podgrafem. +\s{Pozorování:} +Pokud je graf~$H$ podgrafem grafu~$G$, pak je také jeho minorem. +Opačně to neplatí: například $C_3$ je minorem libovolné delší kružnice, +ale určitě ne jejím podgrafem. \s{Definice:} -Tøída grafù $\cal C$ je {\I minorovì uzavøená,} pokud kdykoliv $G\in {\cal C}$ -a $H\preceq G$, platí také $H \in {\cal C}$. +Třída grafů $\cal C$ je {\I minorově uzavřená,} pokud kdykoliv $G\in {\cal C}$ +a $H\preceq G$, platí také $H \in {\cal C}$. -\s{Pøíklady:} -Tøída v¹ech grafù a prázdná tøída jsou jistì minorovì uzavøené. Tìm øíkáme {\I triviální} -tøídy. Mezi ty netriviální patøí tøeba lesy, rovinné grafy, grafy nakreslitelné na dal¹í -plochy, grafy nakreslitelné do ${\bb R}^3$ tak, ¾e ¾ádná kru¾nice netvoøí uzel. +\s{Příklady:} +Třída vÅ¡ech grafů a prázdná třída jsou jistě minorově uzavřené. Těm říkáme {\I triviální} +třídy. Mezi ty netriviální patří třeba lesy, rovinné grafy, grafy nakreslitelné na další +plochy, grafy nakreslitelné do ${\bb R}^3$ tak, že žádná kružnice netvoří uzel. \def\Forb{{\rm Forb}} \s{Definice:} -Pro tøídu grafù ${\cal C}$ definujeme $\Forb({\cal C})$ jako tøídu v¹ech grafù, -jejich¾ minorem není ¾ádný graf z~${\cal C}$. Pro zjednodu¹ení znaèení budeme pro -koneèné tøídy psát $\Forb(G_1,\ldots,G_k)$ namísto $\Forb(\{G_1,\ldots,G_k\})$. - -\s{Pøíklady:} -$\Forb(K_2)$ je tøída v¹ech grafù, které neobsahují ¾ádnou hranu. -$\Forb(C_3)$ je tøída v¹ech lesù. -$\Forb(K_5,K_{3,3})$ jsou v¹echny rovinné grafy -- to je minorová analogie -Kuratowského vìty (pokud graf~$G$ obsahuje dìlení grafu~$H$, pak je $H\preceq G$; -opaènì to obecnì není pravda, ale zrovna pro dvojici $K_5$ a $K_{3,3}$ to funguje; +Pro třídu grafů ${\cal C}$ definujeme $\Forb({\cal C})$ jako třídu vÅ¡ech grafů, +jejichž minorem není žádný graf z~${\cal C}$. Pro zjednoduÅ¡ení značení budeme pro +konečné třídy psát $\Forb(G_1,\ldots,G_k)$ namísto $\Forb(\{G_1,\ldots,G_k\})$. + +\s{Příklady:} +$\Forb(K_2)$ je třída vÅ¡ech grafů, které neobsahují žádnou hranu. +$\Forb(C_3)$ je třída vÅ¡ech lesů. +$\Forb(K_5,K_{3,3})$ jsou vÅ¡echny rovinné grafy -- to je minorová analogie +Kuratowského věty (pokud graf~$G$ obsahuje dělení grafu~$H$, pak je $H\preceq G$; +opačně to obecně není pravda, ale zrovna pro dvojici $K_5$ a $K_{3,3}$ to funguje; zkuste si sami). -Lze ka¾dou minorovì uzavøenou tøídu~${\cal C}$ zapsat jako $\Forb({\cal F})$ -pro nìjakou tøídu~${\cal F}$ zakázaných minorù? Zajisté ano, staèí napøíklad -zvolit~${\cal F}$ jako doplnìk tøídy~${\cal C}$. Slavná Robertsonova-Seymourova -vìta \cite{rs:wagner} dokonce zaruèuje existenci {\I koneèné} tøídy zakázaných minorù. -To není samo sebou, dokazuje se to dosti obtí¾nì (a~je to jedna z~nejslavnìj¹ích kombinatorických -vìt za~posledních mnoho let), ale plyne z~toho spousta zajímavých dùsledkù. -My si vystaèíme s~daleko jednodu¹¹ími prostøedky a zájemce o~hlub¹í studium minorové -teorie odká¾eme na Diestelovu knihu~\cite{diestel:gt}. - -Ve~zbytku této sekce doká¾eme následující vìtu, která je zobecnìním klasického -tvrzení o~hustotì rovinných grafù na minorovì uzavøené tøídy: - -\s{Definice:} {\I Hustotou} neprázdného grafu~$G$ nazveme $\varrho(G) = \vert E(G) \vert -/ \vert V(G) \vert$. Hustotou tøídy $\varrho({\cal C})$ pak nazveme supremum z~hustot v¹ech -neprázdných grafù le¾ících v~této tøídì. - -\s{Vìta (o hustotì minorovì uzavøených tøíd):} -Pokud je tøída grafù $\cal C$ minorovì uzavøená a netriviální (alespoò jeden graf v~ní le¾í -a alespoò jeden nele¾í), pak má koneènou hustotu. - -\s{Dùsledek:} -Pokud pou¾íváme kontrahující Borùvkùv algoritmus na grafy le¾ící v~nìjaké netriviální -minorovì uzavøené tøídì, pak v¹echny grafy, které algoritmus v~prùbìhu výpoètu sestrojí, -le¾í také v~této tøídì, tak¾e na odhad jejich hustoty mù¾eme pou¾ít pøedchozí vìtu. -Opìt vyjde, ¾e èasová slo¾itost algoritmu je lineární. - -\>{\I Dùkaz vìty:} -Uká¾eme nejprve, ¾e pro ka¾dou tøídu $\cal C$ existuje nìjaké~$k$ takové, ¾e +Lze každou minorově uzavřenou třídu~${\cal C}$ zapsat jako $\Forb({\cal F})$ +pro nějakou třídu~${\cal F}$ zakázaných minorů? Zajisté ano, stačí například +zvolit~${\cal F}$ jako doplněk třídy~${\cal C}$. Slavná Robertsonova-Seymourova +věta \cite{rs:wagner} dokonce zaručuje existenci {\I konečné} třídy zakázaných minorů. +To není samo sebou, dokazuje se to dosti obtížně (a~je to jedna z~nejslavnějších kombinatorických +vět za~posledních mnoho let), ale plyne z~toho spousta zajímavých důsledků. +My si vystačíme s~daleko jednoduššími prostředky a zájemce o~hlubší studium minorové +teorie odkážeme na Diestelovu knihu~\cite{diestel:gt}. + +Ve~zbytku této sekce dokážeme následující větu, která je zobecněním klasického +tvrzení o~hustotě rovinných grafů na minorově uzavřené třídy: + +\s{Definice:} {\I Hustotou} neprázdného grafu~$G$ nazveme $\varrho(G) = \vert E(G) \vert +/ \vert V(G) \vert$. Hustotou třídy $\varrho({\cal C})$ pak nazveme supremum z~hustot vÅ¡ech +neprázdných grafů ležících v~této třídě. + +\s{Věta (o hustotě minorově uzavřených tříd):} +Pokud je třída grafů $\cal C$ minorově uzavřená a netriviální (alespoň jeden graf v~ní leží +a alespoň jeden neleží), pak má konečnou hustotu. + +\s{Důsledek:} +Pokud používáme kontrahující Borůvkův algoritmus na grafy ležící v~nějaké netriviální +minorově uzavřené třídě, pak vÅ¡echny grafy, které algoritmus v~průběhu výpočtu sestrojí, +leží také v~této třídě, takže na odhad jejich hustoty můžeme použít předchozí větu. +Opět vyjde, že časová složitost algoritmu je lineární. + +\>{\I Důkaz věty:} +Ukážeme nejprve, že pro každou třídu $\cal C$ existuje nějaké~$k$ takové, že ${\cal C} \subseteq \Forb(K_k)$. -U¾ víme, ¾e ${\cal C}$ lze zapsat jako $\Forb({\cal F})$ pro nìjakou tøídu~${\cal F}$. -Oznaème~$F$ graf z~${\cal F}$ s~nejmen¹ím poètem vrcholù; pokud existuje více takových, -vybereme libovolný. Hledané~$k$ zvolíme jako poèet vrcholù tohoto grafu. +Už víme, že ${\cal C}$ lze zapsat jako $\Forb({\cal F})$ pro nějakou třídu~${\cal F}$. +Označme~$F$ graf z~${\cal F}$ s~nejmenším počtem vrcholů; pokud existuje více takových, +vybereme libovolný. Hledané~$k$ zvolíme jako počet vrcholů tohoto grafu. -Inkluze tvaru ${\cal A}\subseteq {\cal B}$ je ekvivalentní tomu, ¾e kdykoliv nìjaký graf~$G$ -nele¾í v~${\cal B}$, pak nele¾í ani v~${\cal A}$. Mìjme tedy nìjaký graf $G\not\in\Forb(K_k)$. -Proto $K_k \preceq G$. Ov¹em triviálnì platí $F\preceq K_k$ a relace \uv{být minorem} -je tranzitivní, tak¾e $F\preceq G$, a~proto $G\not\in {\cal C}$. +Inkluze tvaru ${\cal A}\subseteq {\cal B}$ je ekvivalentní tomu, že kdykoliv nějaký graf~$G$ +neleží v~${\cal B}$, pak neleží ani v~${\cal A}$. Mějme tedy nějaký graf $G\not\in\Forb(K_k)$. +Proto $K_k \preceq G$. OvÅ¡em triviálně platí $F\preceq K_k$ a relace \uv{být minorem} +je tranzitivní, takže $F\preceq G$, a~proto $G\not\in {\cal C}$. -Víme tedy, ¾e ${\cal C} \subseteq \Forb(K_k)$. Proto musí platit $\varrho({\cal C}) \le -\varrho(\Forb(K_k))$. Tak¾e postaèuje omezit hustotu tøíd s~jedním zakázaným minorem, -který je úplným grafem, a~to plyne z~následující Maderovy vìty. +Víme tedy, že ${\cal C} \subseteq \Forb(K_k)$. Proto musí platit $\varrho({\cal C}) \le +\varrho(\Forb(K_k))$. Takže postačuje omezit hustotu tříd s~jedním zakázaným minorem, +který je úplným grafem, a~to plyne z~následující Maderovy věty. \qed -\s{Vìta (Maderova):} -Pro ka¾dé~$k\ge 2$ existuje $c(k)$ takové, ¾e kdykoliv má graf hustotu alespoò $c(k)$, -obsahuje jako podgraf nìjaké dìlení grafu~$K_k$. +\s{Věta (Maderova):} +Pro každé~$k\ge 2$ existuje $c(k)$ takové, že kdykoliv má graf hustotu alespoň $c(k)$, +obsahuje jako podgraf nějaké dělení grafu~$K_k$. \proof Viz Diestel \cite{diestel:gt}. -\h{Jarníkùv algoritmus s Fibonacciho haldou} +\h{Jarníkův algoritmus s Fibonacciho haldou} -Pùvodní Jarníkùv algoritmus s~haldou má díky ní slo¾itost $\O(m\log n)$, to zlep¹íme pou¾itím -Fibonacciho haldy $H$, do~které si pro ka¾dý vrchol sousedící se zatím vybudovaným stromem~$T$ -ulo¾íme nejlevnìj¹í z~hran vedoucích mezi tímto vrcholem a stromem~$T$. Tyto hrany bude halda -udr¾ovat uspoøádané podle vah. +Původní Jarníkův algoritmus s~haldou má díky ní složitost $\O(m\log n)$, to zlepšíme použitím +Fibonacciho haldy $H$, do~které si pro každý vrchol sousedící se zatím vybudovaným stromem~$T$ +uložíme nejlevnější z~hran vedoucích mezi tímto vrcholem a stromem~$T$. Tyto hrany bude halda +udržovat uspořádané podle vah. \newcount\algcnt -\s{Algoritmus: Jarníkùv algoritmus~\#2 (Fredman, Tarjan \cite{ft:fibonacci})} +\s{Algoritmus: Jarníkův algoritmus~\#2 (Fredman, Tarjan \cite{ft:fibonacci})} \algo -\:Zaèneme libovolným vrcholem $v_0$, $T\leftarrow \{v_0\}$. -\:Do~haldy $H$ umístíme v¹echny hrany vedoucí z~$v_0$. +\:Začneme libovolným vrcholem $v_0$, $T\leftarrow \{v_0\}$. +\:Do~haldy $H$ umístíme vÅ¡echny hrany vedoucí z~$v_0$. \:Opakujeme, dokud $H\neq\emptyset$: -\::$vw\leftarrow \(H)$, pøièem¾ $v\not\in T, w\in T$. +\::$vw\leftarrow \(H)$, přičemž $v\not\in T, w\in T$. \::$T\leftarrow T\cup\{vw\}$ -\::Pro v¹echny sousedy $u$ vrcholu $v$, kteøí dosud nejsou v~$T$, upravíme haldu: -\:::Pokud je¹tì v~$H$ není hrana incidentní s~$u$, pøidáme hranu~$uv$. -\:::Pokud u¾ tam nìjaká taková hrana je a je-li tì¾¹í ne¾ $uv$, nahradíme ji +\::Pro vÅ¡echny sousedy $u$ vrcholu $v$, kteří dosud nejsou v~$T$, upravíme haldu: +\:::Pokud jeÅ¡tě v~$H$ není hrana incidentní s~$u$, přidáme hranu~$uv$. +\:::Pokud už tam nějaká taková hrana je a je-li těžší než $uv$, nahradíme ji hranou~$uv$ a provedeme \. \global\algcnt=\itemcount \endalgo -\>Správnost algoritmu pøímo plyne ze~správnosti Jarníkova algoritmu. +\>Správnost algoritmu přímo plyne ze~správnosti Jarníkova algoritmu. -\s{Èasová slo¾itost:} -Slo¾itost tohoto algoritmu bude $\O(m+n\log n)$, nebo» vnìj¹í cyklus se provede -nanejvý¹ $n$-krát, za~\ v~nìm tedy zaplatíme celkem $\O(n\log n)$, za~pøidávání -vrcholù do~$H$ a~nalézání nejlevnìj¹ích hran zaplatíme celkem $\O(m)$ (na~ka¾dou hranu takto -sáhneme nanejvý¹ dvakrát), za~sni¾ování vah vrcholù v~haldì rovnì¾ pouze $\O(m)$ -(nanejvý¹ $m$-krát provedu porovnání vah a \ v~kroku~\the\algcnt\ za~$\O(1)$). +\s{Časová složitost:} +Složitost tohoto algoritmu bude $\O(m+n\log n)$, neboÅ¥ vnější cyklus se provede +nanejvýš $n$-krát, za~\ v~něm tedy zaplatíme celkem $\O(n\log n)$, za~přidávání +vrcholů do~$H$ a~nalézání nejlevnějších hran zaplatíme celkem $\O(m)$ (na~každou hranu takto +sáhneme nanejvýš dvakrát), za~snižování vah vrcholů v~haldě rovněž pouze $\O(m)$ +(nanejvýš $m$-krát provedu porovnání vah a \ v~kroku~\the\algcnt\ za~$\O(1)$). -Toto zlep¹ení je dùle¾itìj¹í, ne¾ by se mohlo zdát, proto¾e nám pro grafy s~mnoha hranami -(konkrétnì pro grafy s~$m=\Omega(n\log n)$) dává lineární algoritmus. +Toto zlepÅ¡ení je důležitější, než by se mohlo zdát, protože nám pro grafy s~mnoha hranami +(konkrétně pro grafy s~$m=\Omega(n\log n)$) dává lineární algoritmus. -\h{Kombinace Jarníkova a Borùvkova algoritmu} +\h{Kombinace Jarníkova a Borůvkova algoritmu} -K~dal¹ímu zlep¹ení dojde, kdy¾ pøed pøedchozím algoritmem spustíme $\log\log n$ cyklù Borùvkova -algoritmu s~kontrahováním vrcholù, èím¾ graf zahustíme. +K~dalšímu zlepÅ¡ení dojde, když před předchozím algoritmem spustíme $\log\log n$ cyklů Borůvkova +algoritmu s~kontrahováním vrcholů, čímž graf zahustíme. -\s{Algoritmus: Jarníkùv algoritmus~\#3 (pùvod neznámý)} +\s{Algoritmus: Jarníkův algoritmus~\#3 (původ neznámý)} \algo -\:Provedeme $\log\log n$ cyklù upraveného Borùvkova algoritmu s~kontrahováním hran popsaného vý¹e. -\:Pokraèujeme Jarníkovým algoritmem~\#2. +\:Provedeme $\log\log n$ cyklů upraveného Borůvkova algoritmu s~kontrahováním hran popsaného výše. +\:Pokračujeme Jarníkovým algoritmem~\#2. \endalgo -\s{Èasová slo¾itost:} -Slo¾itost první èásti je $\O(m\log\log n)$. -Poèet vrcholù se po~první èásti algoritmu sní¾í na~$n'\leq n/\log n$ a slo¾itost druhé èásti bude -tedy nanejvý¹ $\O(m+n'\log n')=\O(m)$. +\s{Časová složitost:} +Složitost první části je $\O(m\log\log n)$. +Počet vrcholů se po~první části algoritmu sníží na~$n'\leq n/\log n$ a složitost druhé části bude +tedy nanejvýš $\O(m+n'\log n')=\O(m)$. -\h{Jarníkùv algoritmus s~omezením velikosti haldy} +\h{Jarníkův algoritmus s~omezením velikosti haldy} -Je¹tì vìt¹ího zrychlení dosáhneme, omezíme-li Jarníkovu algoritmu \#2 vhodnì -velikost haldy, tak¾e nám nalezne jednotlivé podkostøièky zastavené v~rùstu -pøeteèením haldy. Podle tìchto podkostøièek graf následnì skontrahujeme -a budeme pokraèovat s~mnohem men¹ím grafem. +JeÅ¡tě většího zrychlení dosáhneme, omezíme-li Jarníkovu algoritmu \#2 vhodně +velikost haldy, takže nám nalezne jednotlivé podkostřičky zastavené v~růstu +přetečením haldy. Podle těchto podkostřiček graf následně skontrahujeme +a budeme pokračovat s~mnohem menším grafem. -\s{Algoritmus: Jarníkùv algoritmus~\#4 (Fredman, Tarjan \cite{ft:fibonacci})} +\s{Algoritmus: Jarníkův algoritmus~\#4 (Fredman, Tarjan \cite{ft:fibonacci})} \algo -\:Opakujeme, dokud máme netriviální $G$ (s alespoò jednou hranou): +\:Opakujeme, dokud máme netriviální $G$ (s alespoň jednou hranou): \::$t\leftarrow\vert V(G)\vert$. -\::Zvolíme $k\leftarrow 2^{2m/t}$ (velikost haldy). +\::Zvolíme $k\leftarrow 2^{2m/t}$ (velikost haldy). \::$T\leftarrow\emptyset$. -\::Opakujeme, dokud existují vrcholy mimo $T$: +\::Opakujeme, dokud existují vrcholy mimo $T$: \:::Najdeme vrchol $v_0$ mimo $T$. -\:::Spustíme Jarníkùv alg. \#2 pro celý graf od $v_0$. Zastavíme ho, pokud: +\:::Spustíme Jarníkův alg. \#2 pro celý graf od $v_0$. Zastavíme ho, pokud: \global\algcnt=\itemcount -\::::$\vert H\vert\geq k$ (byla pøekroèena velikost haldy) nebo -\::::$H=\emptyset$ (do¹li sousedé) nebo -\::::do $T$ jsme pøidali hranu oboustrannì incidentní s~hranami v~$T$ (pøipojili -jsme novou podkostru k~nìjaké u¾ nalezené). -\::Kontrahujeme $G$ podle podkoster nalezených v~$T$. +\::::$\vert H\vert\geq k$ (byla překročena velikost haldy) nebo +\::::$H=\emptyset$ (doÅ¡li sousedé) nebo +\::::do $T$ jsme přidali hranu oboustranně incidentní s~hranami v~$T$ (připojili +jsme novou podkostru k~nějaké už nalezené). +\::Kontrahujeme $G$ podle podkoster nalezených v~$T$. \endalgo -\s{Pozorování:} -Pokud algoritmus je¹tì neskonèil, je ka¾dá z~nalezených podkoster v~$T$ incidentní s~alespoò $k$ hranami -(do toho poèítáme i vnitøní hrany vedoucí mezi vrcholy podkostry). -Jak to vypadá pro jednotlivá ukonèení: +\s{Pozorování:} +Pokud algoritmus jeÅ¡tě neskončil, je každá z~nalezených podkoster v~$T$ incidentní s~alespoň $k$ hranami +(do toho počítáme i vnitřní hrany vedoucí mezi vrcholy podkostry). +Jak to vypadá pro jednotlivá ukončení: \numlist\ndotted \itemcount=\algcnt -\:$\vert H\vert\geq k$ -- v¹echny hrany v~haldì jsou incidentní s~$T$ a navzájem rùzné, tak¾e incidentních je dost. -\:$H=\emptyset$ -- nemù¾e nastat, algoritmus by skonèil. -\:Pøipojím se k~u¾ existující podkostøe -- jen ji zvìt¹ím. +\:$\vert H\vert\geq k$ -- vÅ¡echny hrany v~haldě jsou incidentní s~$T$ a navzájem různé, takže incidentních je dost. +\:$H=\emptyset$ -- nemůže nastat, algoritmus by skončil. +\:Připojím se k~už existující podkostře -- jen ji zvětším. \endlist -\s{Èasová slo¾itost:} -Dùsledkem pøedchozího pozorování je, ¾e poèet podkoster v~jednom prùchodu je nanejvý¹ -$2m/k$. Pro $t'$ a $k'$ v následujícím kroku potom platí $t'\leq 2m/k$ a $k'=2^{2m/t'}\geq 2^k$. -Prùchodù bude tedy nanejvý¹ $\log^* n$\foot{$\log^* n$ je inverzní funkce k~\uv{vì¾i -z~mocnin}, èili $\min\{i:\log^{(i)} n<1 \}$, kde $\log^{(i)} n$ je $i$-krát iterovaný -logaritmus.}, proto¾e prùchod s~$k>n$ bude u¾ urèitì poslední. -Pøitom jeden vnìj¹í prùchod trvá $\O(m+t\log k)$, co¾ je pro $k=2^{2m/t}$ -rovno $\O(m)$. Celkovì tedy algoritmus pobì¾í v~èase $\O(m\log^{*}n)$. +\s{Časová složitost:} +Důsledkem předchozího pozorování je, že počet podkoster v~jednom průchodu je nanejvýš +$2m/k$. Pro $t'$ a $k'$ v následujícím kroku potom platí $t'\leq 2m/k$ a $k'=2^{2m/t'}\geq 2^k$. +Průchodů bude tedy nanejvýš $\log^* n$\foot{$\log^* n$ je inverzní funkce k~\uv{věži +z~mocnin}, čili $\min\{i:\log^{(i)} n<1 \}$, kde $\log^{(i)} n$ je $i$-krát iterovaný +logaritmus.}, protože průchod s~$k>n$ bude už určitě poslední. +Přitom jeden vnější průchod trvá $\O(m+t\log k)$, což je pro $k=2^{2m/t}$ +rovno $\O(m)$. Celkově tedy algoritmus poběží v~čase $\O(m\log^{*}n)$. -I~odhad $\log^* n$ je ale pøíli¹ hrubý, proto¾e nezaèínáme s~haldou velikosti~1, nýbr¾ -$2^{2m/n}$. Mù¾eme tedy poèet prùchodù pøesnìji omezit funkcí $\beta(m,n)=\min\{i:\log^{(i)}n, \ reprezentované mno¾iny (mohou být i nedefinovaná, pokud je mno¾ina moc malá), +\:\, \ reprezentované množiny (mohou být i nedefinovaná, pokud je množina moc malá), -\:{\I pøihrádky} $P_0, \ldots, P_{\sqrt{U}}$ obsahující zbývající -hodnoty.\foot{Alespoò jedno z~\, \ musí být ulo¾eno zvlá¹», -aby strom obsahující pouze jednu hodnotu nemìl ¾ádné podstromy. -My jsme pro eleganci struktury zvolili ulo¾it zvlá¹» obojí.} +\:{\I přihrádky} $P_0, \ldots, P_{\sqrt{U}}$ obsahující zbývající +hodnoty.\foot{Alespoň jedno z~\, \ musí být uloženo zvlášť, +aby strom obsahující pouze jednu hodnotu neměl žádné podstromy. +My jsme pro eleganci struktury zvolili uložit zvlášť obojí.} Hodnota $x$ padne do~$P_{\lfloor x/\sqrt{U} \rfloor}$. -Ka¾dá pøihrádka je ulo¾ena jako VEBT($\sqrt{U}$), který obsahuje pøíslu¹ná -èísla $\bmod\sqrt{U}$. [Bity ka¾dého èísla jsme tedy rozdìlili na~vy¹¹ích $k/2$, -které indexují pøihrádku, a~ni¾¹ích $k/2$ uvnitø pøihrádky.] +Každá přihrádka je uložena jako VEBT($\sqrt{U}$), který obsahuje přísluÅ¡ná +čísla $\bmod\sqrt{U}$. [Bity každého čísla jsme tedy rozdělili na~vyšších $k/2$, +které indexují přihrádku, a~nižších $k/2$ uvnitř přihrádky.] -\:Navíc je¹tì {\I \uv{sumární}} VEBT($\sqrt{U}$) obsahující èísla neprázdných pøihrádek. +\:Navíc jeÅ¡tě {\I \uv{sumární}} VEBT($\sqrt{U}$) obsahující čísla neprázdných přihrádek. \endlist -\s{Operace} se~strukturou budeme provádìt následovnì. Budeme si pøitom pøedstavovat, -¾e v~pøihrádkách jsou ulo¾ena pøímo èísla reprezentované mno¾iny, nikoliv jen èásti -jejich bitù -- z~èísla pøihrádky a hodnoty uvnitø pøihrádky ostatnì doká¾eme celou -hodnotu rekonstruovat a naopak hodnotu kdykoliv rozlo¾it na~tyto èásti. +\s{Operace} se~strukturou budeme provádět následovně. Budeme si přitom představovat, +že v~přihrádkách jsou uložena přímo čísla reprezentované množiny, nikoliv jen části +jejich bitů -- z~čísla přihrádky a hodnoty uvnitř přihrádky ostatně dokážeme celou +hodnotu rekonstruovat a naopak hodnotu kdykoliv rozložit na~tyto části. -\>\ -- minimum nalezneme v~koøeni v~èase $\O(1)$. +\>\ -- minimum nalezneme v~kořeni v~čase $\O(1)$. -\>$\(x)$ -- pøímoèaøe rekurzí pøes pøihrádky v~èase $\O(k)$. +\>$\(x)$ -- přímočaře rekurzí přes přihrádky v~čase $\O(k)$. \>$\(x)$: \algo -\:O¹etøíme triviální stromy (prázdný a jednoprvkový) -\:Je-li tøeba, prohodíme $x$ s \, \. -\:Prvek $x$ padne do pøihrádky $P_i$, která je buï: -\::prázdná $\Rightarrow$ \ hodnoty~$i$ do~sumárního stromu a zalo¾ení -triviálního stromu pro pøihrádku; nebo -\::neprázdná $\Rightarrow$ pøevedeme na~\ v~podstromu. +\:OÅ¡etříme triviální stromy (prázdný a jednoprvkový) +\:Je-li třeba, prohodíme $x$ s \, \. +\:Prvek $x$ padne do přihrádky $P_i$, která je buď: +\::prázdná $\Rightarrow$ \ hodnoty~$i$ do~sumárního stromu a založení +triviálního stromu pro přihrádku; nebo +\::neprázdná $\Rightarrow$ převedeme na~\ v~podstromu. \endalgo -V~ka¾dém pøípadì buï rovnou skonèíme nebo pøevedeme na~\ v~jednom stromu -ni¾¹ího øádu a k~tomu vykonáme konstantní práci. Celkem tedy $\O(k)$. +V~každém případě buď rovnou skončíme nebo převedeme na~\ v~jednom stromu +nižšího řádu a k~tomu vykonáme konstantní práci. Celkem tedy $\O(k)$. -\>$\(x)$ -- smazání prvku bude opìt pracovat v~èase $\O(k)$. +\>$\(x)$ -- smazání prvku bude opět pracovat v~čase $\O(k)$. \algo -\:O¹etøíme triviální stromy (jednoprvkový a dvouprvkový). -\:Pokud ma¾eme \ (analogicky \), nahradíme ho minimem -z~první neprázdné pøihrádky (tu najdeme podle sumárního stromu v~konstantním èase) -a pøevedeme na~\ v~této pøihrádce. -\:Prvek~$x$ padne do~pøihrádky $P_i$, která je buï: -\::jednoprvková $\Rightarrow$ zru¹ení pøihrádky a \ ze~sumárního stromu; nebo -\::vìt¹í $\Rightarrow$ \ ve~stromu pøihrádky. +\:OÅ¡etříme triviální stromy (jednoprvkový a dvouprvkový). +\:Pokud mažeme \ (analogicky \), nahradíme ho minimem +z~první neprázdné přihrádky (tu najdeme podle sumárního stromu v~konstantním čase) +a převedeme na~\ v~této přihrádce. +\:Prvek~$x$ padne do~přihrádky $P_i$, která je buď: +\::jednoprvková $\Rightarrow$ zruÅ¡ení přihrádky a \ ze~sumárního stromu; nebo +\::větší $\Rightarrow$ \ ve~stromu přihrádky. \endalgo -\>$\(x)$ -- nejmen¹í prvek vìt¹í ne¾~$x$, opìt v~èase $\O(k)$: +\>$\(x)$ -- nejmenší prvek větší než~$x$, opět v~čase $\O(k)$: \algo -\:Triviální pøípady: pokud $x<\$, vrátíme \; pokud $x\ge\$, -vrátíme, ¾e následník neexistuje. -\:Prvek~$x$ padne do~pøihrádky $P_i$ a buïto: -\::$P_i$ je prázdná nebo $x=\(P_i)$ $\Rightarrow$ pomocí \ -v~sumárním stromu najdeme nejbli¾¹í dal¹í neprázdnou pøihrádku $P_j$: -\:::existuje-li $\Rightarrow$ vrátíme $\(P_j)$, -\:::neexistuje-li $\Rightarrow$ vrátíme \. -\::nebo $x<\(P_i)$ $\Rightarrow$ pøevedeme na~\ v~$P_i$. +\:Triviální případy: pokud $x<\$, vrátíme \; pokud $x\ge\$, +vrátíme, že následník neexistuje. +\:Prvek~$x$ padne do~přihrádky $P_i$ a buďto: +\::$P_i$ je prázdná nebo $x=\(P_i)$ $\Rightarrow$ pomocí \ +v~sumárním stromu najdeme nejbližší další neprázdnou přihrádku $P_j$: +\:::existuje-li $\Rightarrow$ vrátíme $\(P_j)$, +\:::neexistuje-li $\Rightarrow$ vrátíme \. +\::nebo $x<\(P_i)$ $\Rightarrow$ převedeme na~\ v~$P_i$. \endalgo -Slo¾itosti operací jsou pìkné, ale nesmíme zapomenout, ¾e strukturu -je na~poèátku nutné inicializovat, co¾ trvá $\Omega(\sqrt U)$.\foot{Svádí -to k~nápadu ponechat pøihrádky neinicializované a nejdøíve se v¾dy zeptat -sumárního stromu, ale tím bychom si pokazili èasovou slo¾itost.} -Z~následujících úvah ov¹em vyplyne, ¾e si inicializaci mù¾eme +Složitosti operací jsou pěkné, ale nesmíme zapomenout, že strukturu +je na~počátku nutné inicializovat, což trvá $\Omega(\sqrt U)$.\foot{Svádí +to k~nápadu ponechat přihrádky neinicializované a nejdříve se vždy zeptat +sumárního stromu, ale tím bychom si pokazili časovou složitost.} +Z~následujících úvah ovÅ¡em vyplyne, že si inicializaci můžeme odpustit. \h{Modely inicializace} -\>Jak mù¾e být definován obsah pamìti na~poèátku výpoètu: +\>Jak může být definován obsah paměti na~počátku výpočtu: -\s{\uv{Pøi odchodu zhasni}:} Zavedeme, ¾e pamì» RAMu je na~poèátku -inicializována nulami a program ji po~sobì musí uklidit (to je nutné, -aby programy ¹lo iterovat). To u~VEBT není problém zaøídit. +\s{\uv{Při odchodu zhasni}:} Zavedeme, že paměť RAMu je na~počátku +inicializována nulami a program ji po~sobě musí uklidit (to je nutné, +aby programy Å¡lo iterovat). To u~VEBT není problém zařídit. -\s{Neinicializovano:} Na~¾ádné konkrétní hodnoty se nemù¾eme spolehnout, -ale je definováno, ¾e neinicializovanou buòku mù¾eme pøeèíst a dostaneme -nìjakou korektní, i kdy¾ libovolnou, hodnotu. Tehdy nám pomù¾e: +\s{Neinicializovano:} Na~žádné konkrétní hodnoty se nemůžeme spolehnout, +ale je definováno, že neinicializovanou buňku můžeme přečíst a dostaneme +nějakou korektní, i když libovolnou, hodnotu. Tehdy nám pomůže: %{\narrower\medskip -\s{Vìta:} Buï $P$ program pro Word-RAM s~nulami inicializovanou -pamìtí, bì¾ící v èase $T(n)$. Pak existuje program~$P'$ pro Word-RAM -s~neinicializovanou pamìtí poèítající toté¾ v~èase~$\O(T(n))$. - -\proof Bìhem výpoètu si budeme pamatovat, do~kterých pamì»ových -bunìk u¾ bylo nìco zapsáno, a~které tedy mají definovanou hodnotu. -Prokládanì ulo¾íme do pamìti dvì pole: -$M$, co¾ bude pamì» pùvodního stroje, a~$L$ -- seznam èísel bunìk -v~$M$, do~kterých u¾ program zapsal. Pøitom $L[0]$ bude udávat -délku seznamu~$L$. - -Program nyní zaène tím, ¾e vynuluje $L[0]$ a bude simulovat pùvodní -program, pøièem¾ kdykoliv ten bude chtít pøeèíst nìjakou buòku -z~$M$, podíváme se do~$L$, zda u¾ je inicializovaná, a~pøípadnì -vrátíme nulu a buòku pøipí¹eme do~$L$. - -To je funkèní, ale pomalé. Redukci tedy vylep¹íme tak, ¾e zalo¾íme dal¹í -prolo¾ené pole~$R$, jeho¾ hodnota $R[i]$ bude øíkat, kde v~$L$ se vyskytuje -èíslo $i$-té buòky, nebo bude neinicializována, pokud -takové místo dosud neexistuje. - -Pøed ètením $M[i]$ se teï podíváme na~$R[i]$ a ovìøíme, zda $R[i]$ nele¾í -mimo seznam~$L$ a zda je $L[R[i]]=i$. Tím v~konstantním èase zjistíme, -jestli je $M[i]$ ji¾ inicializovaná, a~jsme také schopni tuto informaci -v~tém¾e èase udr¾ovat. +\s{Věta:} Buď $P$ program pro Word-RAM s~nulami inicializovanou +pamětí, běžící v čase $T(n)$. Pak existuje program~$P'$ pro Word-RAM +s~neinicializovanou pamětí počítající totéž v~čase~$\O(T(n))$. + +\proof Během výpočtu si budeme pamatovat, do~kterých paměťových +buněk už bylo něco zapsáno, a~které tedy mají definovanou hodnotu. +Prokládaně uložíme do paměti dvě pole: +$M$, což bude paměť původního stroje, a~$L$ -- seznam čísel buněk +v~$M$, do~kterých už program zapsal. Přitom $L[0]$ bude udávat +délku seznamu~$L$. + +Program nyní začne tím, že vynuluje $L[0]$ a bude simulovat původní +program, přičemž kdykoliv ten bude chtít přečíst nějakou buňku +z~$M$, podíváme se do~$L$, zda už je inicializovaná, a~případně +vrátíme nulu a buňku připíšeme do~$L$. + +To je funkční, ale pomalé. Redukci tedy vylepšíme tak, že založíme další +proložené pole~$R$, jehož hodnota $R[i]$ bude říkat, kde v~$L$ se vyskytuje +číslo $i$-té buňky, nebo bude neinicializována, pokud +takové místo dosud neexistuje. + +Před čtením $M[i]$ se teď podíváme na~$R[i]$ a ověříme, zda $R[i]$ neleží +mimo seznam~$L$ a zda je $L[R[i]]=i$. Tím v~konstantním čase zjistíme, +jestli je $M[i]$ již inicializovaná, a~jsme také schopni tuto informaci +v~témže čase udržovat. \qed %\medskip} -\s{\uv{Minové pole}:} Neinicializované buòky není ani dovoleno èíst. -V~tomto pøípadì nejsme schopni deterministické redukce, ale alespoò -mu¾eme pou¾ít randomizovanou -- ukládat si obsah pamìti do~hashovací -tabulky, co¾ pøí pou¾ití universálního hashování dá~slo¾itost $\O(1)$ -na~operaci v~prùmìrném pøípadì. +\s{\uv{Minové pole}:} Neinicializované buňky není ani dovoleno číst. +V~tomto případě nejsme schopni deterministické redukce, ale alespoň +mužeme použít randomizovanou -- ukládat si obsah paměti do~hashovací +tabulky, což pří použití universálního hashování dá~složitost $\O(1)$ +na~operaci v~průměrném případě. -\h{Technické triky} +\h{Technické triky} -VEBT nedosahují zdaleka nejlep¹ích mo¾ných parametrù -- lze sestrojit -i struktury pracující v~konstantním èase. To v~následující kapitole také -udìláme, ale nejdøíve v~této ponìkud technické stati vybudujeme repertoár -základních operací proveditelných na~Word-RAMu v~konstantním èase. +VEBT nedosahují zdaleka nejlepších možných parametrů -- lze sestrojit +i struktury pracující v~konstantním čase. To v~následující kapitole také +uděláme, ale nejdříve v~této poněkud technické stati vybudujeme repertoár +základních operací proveditelných na~Word-RAMu v~konstantním čase. -\>Rozcvièka: {\I nejpravìj¹í jednièka} ve~dvojkovém èísle (hodnota, nikoliv pozice): +\>Rozcvička: {\I nejpravější jednička} ve~dvojkovém čísle (hodnota, nikoliv pozice): \alik{ x&=\0\1\9\9\9\0\1\1\0\0\0\0\0\0 \cr x - 1&=\0\1\9\9\9\0\1\0\1\1\1\1\1\1 \cr x \land (x - 1)&=\0\1\9\9\9\0\1\0\0\0\0\0\0\0 \cr x \oplus (x \land (x - 1))&=\0\0\9\9\9\0\0\1\0\0\0\0\0\0 \cr} -\>Nyní uká¾eme, jak RAM pou¾ívat jako vektorový poèítaè, který umí paralelnì -poèítat se v¹emi prvky vektoru, pokud se dají zakódovat do~jediného slova. -Libovolný $n$-slo¾kový vektor, jeho¾ slo¾ky jsou $b$-bitová èísla -($n(b+1)\le w$), zakódujeme poskládáním jednotlivých slo¾ek vektoru za~sebe, -prolo¾enì nulovými bity: +\>Nyní ukážeme, jak RAM používat jako vektorový počítač, který umí paralelně +počítat se vÅ¡emi prvky vektoru, pokud se dají zakódovat do~jediného slova. +Libovolný $n$-složkový vektor, jehož složky jsou $b$-bitová čísla +($n(b+1)\le w$), zakódujeme poskládáním jednotlivých složek vektoru za~sebe, +proloženě nulovými bity: \nobreak \alik{\0 x_{n-1} \0 x_{n-2} \9\9\9 \0 x_1\0 x_0 \cr} -\>S~vektory budeme provádìt následující operace: (latinkou znaèíme vektory, -alfabetou èísla, \0 a \1 jsou jednotlivé bity, $(\ldots)^k$ je $k$-násobné -opakování binárního zápisu) +\>S~vektory budeme provádět následující operace: (latinkou značíme vektory, +alfabetou čísla, \0 a \1 jsou jednotlivé bity, $(\ldots)^k$ je $k$-násobné +opakování binárního zápisu) \itemize\ibull -\:$\(\alpha)$ -- vytvoøí vektor $(\alpha,\alpha,\ldots,\alpha)$: +\:$\(\alpha)$ -- vytvoří vektor $(\alpha,\alpha,\ldots,\alpha)$: \alik{\alpha*(\0^b\1)^n \cr} -\:$\(x)$ -- seète v¹echny slo¾ky vektoru (pøedpokládáme, ¾e se souèet vejde do~$b$~bitù): +\:$\(x)$ -- sečte vÅ¡echny složky vektoru (předpokládáme, že se součet vejde do~$b$~bitů): \numlist\nalpha -\:vymodulením èíslem $\1^{b+1}$ (proto¾e $\1\0^{b+1}\bmod \1^{b+1}=1$), èi -\:násobením vhodnou konstantou: +\:vymodulením číslem $\1^{b+1}$ (protože $\1\0^{b+1}\bmod \1^{b+1}=1$), či +\:násobením vhodnou konstantou: \setbox0=\hbox{~$x_{n-1}$} \slotwd=\wd0 \def\.{\[]} @@ -294,11 +294,11 @@ $\hrulefill$\cr \rule \[r_{n-1}] \dd \[r_2] \[r_1] \[s_n] \dd \[s_3] \[s_2] \[s_1] \cr } -Zde je výsledkem dokonce vektor v¹ech èásteèných souètù: +Zde je výsledkem dokonce vektor vÅ¡ech částečných součtů: $s_k=\sum_{i=0}^{k-1}x_i$, $r_k=\sum_{i=k}^{n-1}x_i$. \endlist -\:$\(x,y)$ -- paralelní porovnání dvou vektorù: $i$-tá slo¾ka výsledku je~1, pokud +\:$\(x,y)$ -- paralelní porovnání dvou vektorů: $i$-tá složka výsledku je~1, pokud $x_i(\alpha,x)$ -- spoèítá, kolik slo¾ek vektoru~$x$ je men¹ích ne¾~$\alpha$: +\:$\(\alpha,x)$ -- spočítá, kolik složek vektoru~$x$ je menších než~$\alpha$: $$\(\alpha,x) = \(\(\(\alpha),x)).$$ -\:$\(\alpha,x)$ -- zatøídí hodnotu $\alpha$ do~setøídìného vektoru~$x$: +\:$\(\alpha,x)$ -- zatřídí hodnotu $\alpha$ do~setříděného vektoru~$x$: -Zde staèí pomocí operace \ zjistit, na~jaké místo novou hodnotu -zatøídit, a~pak to pomocí bitových operací provést (\uv{roz¹oupnout} -existující hodnoty). +Zde stačí pomocí operace \ zjistit, na~jaké místo novou hodnotu +zatřídit, a~pak to pomocí bitových operací provést (\uv{rozÅ¡oupnout} +existující hodnoty). -\:$\(\alpha)$ -- vytvoøí vektor, jeho¾ slo¾ky jsou bity zadaného èísla -(jinými slovy prolo¾í bity bloky $b$~nul). +\:$\(\alpha)$ -- vytvoří vektor, jehož složky jsou bity zadaného čísla +(jinými slovy proloží bity bloky $b$~nul). -Nejdøíve èíslo~$\alpha$ replikujeme, pak andujeme vhodnou bitovou maskou, -aby v~$i$-té slo¾ce zùstal pouze $i$-tý bit a ostatní se vynulovaly, -a pak provedeme $\$ s~vektorem samých nul. +Nejdříve číslo~$\alpha$ replikujeme, pak andujeme vhodnou bitovou maskou, +aby v~$i$-té složce zůstal pouze $i$-tý bit a ostatní se vynulovaly, +a pak provedeme $\$ s~vektorem samých nul. -\:$\_\varphi(\alpha)$ -- podobnì jako pøedchozí operace, ale bity je¹tì -prohází podle nìjaké pevné funkce $\varphi$: +\:$\_\varphi(\alpha)$ -- podobně jako předchozí operace, ale bity jeÅ¡tě +prohází podle nějaké pevné funkce $\varphi$: -Staèí zvolit bitovou masku, která v~$i$-té slo¾ce ponechá právì $\varphi(i)$-tý bit. +Stačí zvolit bitovou masku, která v~$i$-té složce ponechá právě $\varphi(i)$-tý bit. \finalfix{\goodbreak} -\:$\(x)$ -- dostane vektor nul a jednièek a vytvoøí èíslo, jeho¾ bity -jsou právì slo¾ky vektoru (jinými slovy ¹krtne nuly mezi bity): +\:$\(x)$ -- dostane vektor nul a jedniček a vytvoří číslo, jehož bity +jsou právě složky vektoru (jinými slovy Å¡krtne nuly mezi bity): -Pøedstavíme si, ¾e slo¾ky èísla jsou o~jeden bit krat¹í a provedeme \. -Napøíklad pro $n=4$ a $b=4$: +Představíme si, že složky čísla jsou o~jeden bit kratší a provedeme \. +Například pro $n=4$ a $b=4$: \setbox0=\hbox{$x_3$} \slotwd=\wd0 @@ -353,34 +353,34 @@ Nap \|\z\.\z\.\z\.\z\|\[x_3]\.\z\.\z\.\z\|\z\.\[x_2]\.\z\.\z\|\z\.\z\[x_1]\.\z\|\z\.\z\.\z\.\[x_0]\|\cr } -Jen si musíme dát pozor na~to, ¾e vytvoøený vektor s~krat¹ími slo¾kami -není korektnì prostrkán nulami. Konstrukce \ pomocí modula proto -nebude správnì fungovat a místo $\1^b$ vygeneruje $\0^b$. To mù¾eme -buï o¹etøit zvlá¹», nebo pou¾ít konstrukci pøes násobení, které -to nevadí. +Jen si musíme dát pozor na~to, že vytvořený vektor s~kratšími složkami +není korektně prostrkán nulami. Konstrukce \ pomocí modula proto +nebude správně fungovat a místo $\1^b$ vygeneruje $\0^b$. To můžeme +buď oÅ¡etřit zvlášť, nebo použít konstrukci přes násobení, které +to nevadí. \endlist -\>Nyní je¹tì nìkolik operací s~normálními èísly. Chvíli pøedpokládejme, -¾e pro~$b$-bitová èísla na~vstupu budeme mít k~dispozici $b^2$-bitový -pracovní prostor, tak¾e budeme moci pou¾ívat vektory s~$b$ slo¾kami +\>Nyní jeÅ¡tě několik operací s~normálními čísly. Chvíli předpokládejme, +že pro~$b$-bitová čísla na~vstupu budeme mít k~dispozici $b^2$-bitový +pracovní prostor, takže budeme moci používat vektory s~$b$ složkami po~$b$ bitech. \itemize\ibull -\:$\#1(\alpha)$ -- spoèítá jednièkové bity v~zadaném èísle. +\:$\#1(\alpha)$ -- spočítá jedničkové bity v~zadaném čísle. -Staèí provést \ a následnì \. +Stačí provést \ a následně \. -\:$\_\pi(\alpha)$ -- pøehází bity podle zadané fixní permutace. +\:$\_\pi(\alpha)$ -- přehází bity podle zadané fixní permutace. -Provedeme $\_\pi$ a \ zpìt. +Provedeme $\_\pi$ a \ zpět. -\:$\(\alpha)$ -- Least Significant Bit (pozice nejni¾¹í jednièky): +\:$\(\alpha)$ -- Least Significant Bit (pozice nejnižší jedničky): -Podobnì jako v~rozcvièce nejdøíve vytvoøíme èíslo, které obsahuje -nejni¾¹í jednièku a vpravo od~ní dal¹í jednièky, a~pak tyto jednièky -posèítáme pomocí $\#1$: +Podobně jako v~rozcvičce nejdříve vytvoříme číslo, které obsahuje +nejnižší jedničku a vpravo od~ní další jedničky, a~pak tyto jedničky +posčítáme pomocí $\#1$: \alik{ \alpha&= \9\9\9\9\9\1\0\0\0\0\cr @@ -388,22 +388,22 @@ pos \alpha\oplus(\alpha-1)&= \0\9\9\9\0\1\1\1\1\1\cr } -\:$\(\alpha)$ -- Most Significant Bit (pozice nejvy¹¹í jednièky): +\:$\(\alpha)$ -- Most Significant Bit (pozice nejvyšší jedničky): -Z~\ pomocí zrcadlení (operací \). +Z~\ pomocí zrcadlení (operací \). \endlist -\>Poslední dvì operace doká¾eme spoèítat i v~lineárním prostoru, napøíklad -pro \ takto: Rozdìlíme èíslo na bloky velikosti $\lfloor\sqrt{w}\rfloor$. -Pak pro ka¾dý blok zjistíme, zda v~nìm je aspoò jedna jednièka, zavoláním -$\(0,x)$. Pomocí \ z~toho dostaneme slovo~$y$ odmocninové -délky, jeho¾ bity indikují neprázdné bloky. Na~toto èíslo zavoláme pøedchozí -kvadratické \ a zjistíme index nejvy¹¹ího neprázdného bloku. -Ten pak izolujeme a druhým voláním kvadratického algoritmu najdeme nejlevìj¹í -jednièku uvnitø nìj.\foot{Dopou¹tíme se drobného podvùdku -- vektorové operace -pøedpokládaly prostrkané nuly a ty tu nemáme. Mù¾eme si je ale snadno poøídit -a bity, které jsme nulami pøepsali, prostì zpracovat zvlá¹».} +\>Poslední dvě operace dokážeme spočítat i v~lineárním prostoru, například +pro \ takto: Rozdělíme číslo na bloky velikosti $\lfloor\sqrt{w}\rfloor$. +Pak pro každý blok zjistíme, zda v~něm je aspoň jedna jednička, zavoláním +$\(0,x)$. Pomocí \ z~toho dostaneme slovo~$y$ odmocninové +délky, jehož bity indikují neprázdné bloky. Na~toto číslo zavoláme předchozí +kvadratické \ a zjistíme index nejvyššího neprázdného bloku. +Ten pak izolujeme a druhým voláním kvadratického algoritmu najdeme nejlevější +jedničku uvnitř něj.\foot{DopouÅ¡tíme se drobného podvůdku -- vektorové operace +předpokládaly prostrkané nuly a ty tu nemáme. Můžeme si je ale snadno pořídit +a bity, které jsme nulami přepsali, prostě zpracovat zvlášť.} \references \bye diff --git a/8-qheap/8-qheap.tex b/8-qheap/8-qheap.tex index 6168943..23bec98 100644 --- a/8-qheap/8-qheap.tex +++ b/8-qheap/8-qheap.tex @@ -8,233 +8,233 @@ \prednaska{8}{Q-Heaps}{} -V~minulé kapitole jsme zavedli výpoèetní model RAM a nahlédli jsme, -¾e na~nìm mù¾eme snadno simulovat vektorový poèítaè s~vektorovými operacemi pracujícími v~konstantním èase. -Kdy¾ u¾ máme takový poèítaè, pojïme si ukázat, jaké datové struktury na~nìm mù¾eme -vytváøet. +V~minulé kapitole jsme zavedli výpočetní model RAM a nahlédli jsme, +že na~něm můžeme snadno simulovat vektorový počítač s~vektorovými operacemi pracujícími v~konstantním čase. +Když už máme takový počítač, pojďme si ukázat, jaké datové struktury na~něm můžeme +vytvářet. -Svým sna¾ením budeme smìøovat ke~strukturám, které zvládnou operace \ a \ -v~konstantním èase, pøièem¾ bude omezena buïto velikost èísel nebo maximální velikost -struktury nebo obojí. Bez újmy na~obecnosti budeme pøedpokládat, ¾e hodnoty, které do~struktur -ukládáme, jsou navzájem rùzné. +Svým snažením budeme směřovat ke~strukturám, které zvládnou operace \ a \ +v~konstantním čase, přičemž bude omezena buďto velikost čísel nebo maximální velikost +struktury nebo obojí. Bez újmy na~obecnosti budeme předpokládat, že hodnoty, které do~struktur +ukládáme, jsou navzájem různé. -\s{Znaèení:} $w$~bude v¾dy znaèit ¹íøku slova RAMu a $n$~velikost vstupu algoritmu, -v~nìm¾ datovou strukturu vyu¾íváme (speciálnì tedy víme, ¾e $w\ge\log n$). +\s{Značení:} $w$~bude vždy značit šířku slova RAMu a $n$~velikost vstupu algoritmu, +v~němž datovou strukturu využíváme (speciálně tedy víme, že $w\ge\log n$). \h{Word-Encoded B-Tree} -První strukturou, kterou popí¹eme, bude vektorová varianta B-stromu. Nemá je¹tì -tak zajímavé parametry, ale odvozuje se snadno a jsou na~ní dobøe vidìt mnohé -my¹lenky pou¾ívané ve~strukturách slo¾itìj¹ích. +První strukturou, kterou popíšeme, bude vektorová varianta B-stromu. Nemá jeÅ¡tě +tak zajímavé parametry, ale odvozuje se snadno a jsou na~ní dobře vidět mnohé +myÅ¡lenky používané ve~strukturách složitějších. -Pùjde o~obyèejný B-strom s daty v~listech, ov¹em kódovaný vektorovì. Do~listù -stromu budeme ukládat $k$-bitové hodnoty, vnitøní vrcholy budou obsahovat pouze -pomocné klíèe a budou mít nejvý¹e $B$ synù. Strom bude mít hloubku~$h$. Hodnoty -v¹ech klíèù ve~vrcholu si budeme ukládat jako vektor, ukazatele na~jednotlivé +Půjde o~obyčejný B-strom s daty v~listech, ovÅ¡em kódovaný vektorově. Do~listů +stromu budeme ukládat $k$-bitové hodnoty, vnitřní vrcholy budou obsahovat pouze +pomocné klíče a budou mít nejvýše $B$ synů. Strom bude mít hloubku~$h$. Hodnoty +vÅ¡ech klíčů ve~vrcholu si budeme ukládat jako vektor, ukazatele na~jednotlivé syny jakbysmet. -Se~stromem zacházíme jako s~klasickým B-stromem, pøitom operace s~vrcholy -provádíme vektorovì: vyhledání pozice prvku ve~vektoru pomocí operace \, -rozdìlení a sluèování vrcholù pomocí bitových posuvù a maskování, to v¹e -v~èase $\O(1)$. Stromové operace (\, \, \, \, \dots) -tedy stihneme v~èase $\O(h)$. +Se~stromem zacházíme jako s~klasickým B-stromem, přitom operace s~vrcholy +provádíme vektorově: vyhledání pozice prvku ve~vektoru pomocí operace \, +rozdělení a slučování vrcholů pomocí bitových posuvů a maskování, to vÅ¡e +v~čase $\O(1)$. Stromové operace (\, \, \, \, \dots) +tedy stihneme v~čase $\O(h)$. -Zbývá si rozmyslet, co~musí splòovat parametry struktury, aby se v¹echny -vektory ve¹ly do~konstantního poètu slov. Kvùli vektorùm klíèù musí platit -$Bk=\O(w)$. Jeliko¾ strom má a¾~$B^h$ listù a nejvý¹e tolik vnitøních vrcholù, -ukazatele zabírají $\O(h\log B)$ bitù, tak¾e pro vektory ukazatelù potøebujeme, -aby bylo $Bh\log B=\O(w)$. Dobrá volba je napøíklad $B=k=\sqrt w$, $h=\O(1)$, èím¾ -získáme strukturu obsahující $w^{\O(1)}$ prvkù o~$\sqrt w$ bitech, která -pracuje v~konstantním èase. +Zbývá si rozmyslet, co~musí splňovat parametry struktury, aby se vÅ¡echny +vektory veÅ¡ly do~konstantního počtu slov. Kvůli vektorům klíčů musí platit +$Bk=\O(w)$. Jelikož strom má až~$B^h$ listů a nejvýše tolik vnitřních vrcholů, +ukazatele zabírají $\O(h\log B)$ bitů, takže pro vektory ukazatelů potřebujeme, +aby bylo $Bh\log B=\O(w)$. Dobrá volba je například $B=k=\sqrt w$, $h=\O(1)$, čímž +získáme strukturu obsahující $w^{\O(1)}$ prvků o~$\sqrt w$ bitech, která +pracuje v~konstantním čase. \h{Q-Heap} -Pøedchozí struktura má zajímavé vlastnosti, ale èasto je její pou¾ití -znemo¾nìno omezením na~velikost èísel. Popí¹eme tedy o~nìco slo¾itìj¹í -konstrukci od~Fredmana a Willarda \cite{fw90trans}, která doká¾e toté¾, ale s~a¾ $w$-bitovými èísly. -Tato struktura má spí¹e teoretický význam (konstrukce je znaènì komplikovaná -a skryté konstanty nemalé), ale pøekvapivì mnoho my¹lenek je pou¾itelných +Předchozí struktura má zajímavé vlastnosti, ale často je její použití +znemožněno omezením na~velikost čísel. Popíšeme tedy o~něco složitější +konstrukci od~Fredmana a Willarda \cite{fw90trans}, která dokáže totéž, ale s~až $w$-bitovými čísly. +Tato struktura má spíše teoretický význam (konstrukce je značně komplikovaná +a skryté konstanty nemalé), ale překvapivě mnoho myÅ¡lenek je použitelných i prakticky. -\s{Znaèení:} +\s{Značení:} \itemize\ibull -\:$k = \O(w^{1/4})$ -- omezení na~velikost haldy, -\:$r\le k$ -- aktuální poèet prvkù v~haldì, -\:$X=\{x_1, \ldots, x_r\}$ -- ulo¾ené $w$-bitové prvky, oèíslujeme si je tak, aby $x_1 < \ldots < x_r$, -\:$c_i = \msb(x_i \oplus x_{i+1})$ -- nejvy¹¹í bit, ve~kterém se li¹í $x_i$ a +\:$k = \O(w^{1/4})$ -- omezení na~velikost haldy, +\:$r\le k$ -- aktuální počet prvků v~haldě, +\:$X=\{x_1, \ldots, x_r\}$ -- uložené $w$-bitové prvky, očíslujeme si je tak, aby $x_1 < \ldots < x_r$, +\:$c_i = \msb(x_i \oplus x_{i+1})$ -- nejvyšší bit, ve~kterém se liší $x_i$ a $x_{i+1}$, -\:$\rank_X(x)$ -- poèet prvkù mno¾iny~$X$, které jsou men¹í ne¾ $x$ -(pøièem¾ $x$ mù¾e le¾et i mimo~$X$). +\:$\rank_X(x)$ -- počet prvků množiny~$X$, které jsou menší než $x$ +(přičemž $x$ může ležet i mimo~$X$). \endlist -\s{Pøedvýpoèet:} Budeme ochotni obìtovat èas $\O(2^{k^4})$ na~pøedvýpoèet. -To mù¾e znít hrozivì, ale ve~vìt¹inì aplikací bude $k=\log^{1/4} n$, tak¾e -pøedvýpoèet stihneme v~èase $\O(n)$. V~takovém èase mimo jiné stihneme -pøedpoèítat tabulku pro libovolnou funkci, která má vstup dlouhý $\O(k^3)$ -bitù a kterou pro ka¾dý vstup dovedeme vyhodnotit v~polynomiálním èase. -Nadále tedy mù¾eme bezpeènì pøedpokládat, ¾e v¹echny takové funkce -umíme spoèítat v~konstantním èase. - -\s{Iterování:} V¹imnìte si, ¾e jakmile doká¾eme sestrojit haldu s~$k$ prvky -pracující v~konstantním èase, mù¾eme s~konstantním zpomalením sestrojit -i haldu s~$k^{\O(1)}$ prvky. Staèí si hodnoty ulo¾it do~listù stromu -s~vìtvením $k$ a konstantním poètem hladin a v~ka¾dém vnitøním vrcholu -si pamatovat minimum podstromu a Q-Heap s~hodnotami jeho synù. Tak doká¾eme -ka¾dé vlo¾ení i odebrání prvku pøevést na~konstantnì mnoho operací s~Q-Heapy. - -\s{Náèrt} fungování Q-Heapu: -Nad~prvky $x_1,\ldots,x_r$ sestrojíme trii~$T$ a nevìtvící se cesty zkomprimujeme -(nahradíme hranami). Listy trie budou jednotlivá $x_i$, vnitøní vrchol, -který le¾í mezi $x_i$ a $x_{i+1}$, bude testovat $c_i$-tý bit èísla. -Pokud budeme hledat nìkteré z~$x_i$, tyto vnitøní vrcholy (budeme jim -øíkat {\I znaèky}\foot{tøeba turistické pro~orientaci v~lese}) nás správnì dovedou do~pøíslu¹ného listu. Pokud ale -budeme hledat nìjaké jiné~$x$, zavedou nás do~nìjakého na~první pohled -nesouvisejícího listu a teprve tam zjistíme, ¾e jsme zabloudili. K~na¹emu -pøekvapení v¹ak to, kam jsme se dostali, bude staèit ke~spoèítání ranku -prvku a z~rankù u¾ odvodíme i ostatní operace. - -\s{Pøíklad:} Trie pro zadanou mno¾inu èísel. Ohodnocení hran je pouze pro názornost, není -souèástí struktury. +\s{Předvýpočet:} Budeme ochotni obětovat čas $\O(2^{k^4})$ na~předvýpočet. +To může znít hrozivě, ale ve~větÅ¡ině aplikací bude $k=\log^{1/4} n$, takže +předvýpočet stihneme v~čase $\O(n)$. V~takovém čase mimo jiné stihneme +předpočítat tabulku pro libovolnou funkci, která má vstup dlouhý $\O(k^3)$ +bitů a kterou pro každý vstup dovedeme vyhodnotit v~polynomiálním čase. +Nadále tedy můžeme bezpečně předpokládat, že vÅ¡echny takové funkce +umíme spočítat v~konstantním čase. + +\s{Iterování:} VÅ¡imněte si, že jakmile dokážeme sestrojit haldu s~$k$ prvky +pracující v~konstantním čase, můžeme s~konstantním zpomalením sestrojit +i haldu s~$k^{\O(1)}$ prvky. Stačí si hodnoty uložit do~listů stromu +s~větvením $k$ a konstantním počtem hladin a v~každém vnitřním vrcholu +si pamatovat minimum podstromu a Q-Heap s~hodnotami jeho synů. Tak dokážeme +každé vložení i odebrání prvku převést na~konstantně mnoho operací s~Q-Heapy. + +\s{Náčrt} fungování Q-Heapu: +Nad~prvky $x_1,\ldots,x_r$ sestrojíme trii~$T$ a nevětvící se cesty zkomprimujeme +(nahradíme hranami). Listy trie budou jednotlivá $x_i$, vnitřní vrchol, +který leží mezi $x_i$ a $x_{i+1}$, bude testovat $c_i$-tý bit čísla. +Pokud budeme hledat některé z~$x_i$, tyto vnitřní vrcholy (budeme jim +říkat {\I značky}\foot{třeba turistické pro~orientaci v~lese}) nás správně dovedou do~přísluÅ¡ného listu. Pokud ale +budeme hledat nějaké jiné~$x$, zavedou nás do~nějakého na~první pohled +nesouvisejícího listu a teprve tam zjistíme, že jsme zabloudili. K~naÅ¡emu +překvapení vÅ¡ak to, kam jsme se dostali, bude stačit ke~spočítání ranku +prvku a z~ranků už odvodíme i ostatní operace. + +\s{Příklad:} Trie pro zadanou množinu čísel. Ohodnocení hran je pouze pro názornost, není +součástí struktury. \fig{trie.eps}{\hsize} -\s{Lemma R:} $\rank_X(x)$ je urèen jednoznaènì kombinací: +\s{Lemma R:} $\rank_X(x)$ je určen jednoznačně kombinací: \numlist\pnromanp \:tvaru stromu $T$, -\:indexu $i$ listu $x_i$, do~kterého nás zavede hledání hodnoty~$x$ ve~stromu, +\:indexu $i$ listu $x_i$, do~kterého nás zavede hledání hodnoty~$x$ ve~stromu, \:vztahu mezi $x$ a $x_i$ ($xx_i$ nebo $x=x_i$) a \:pozice $b=\msb(x \oplus x_i)$. \endlist -\proof Pokud $x=x_i$, je zjevnì $\rank_X(x) = i$. Pøedpokládejme tedy $x\ne x_i$. -Hodnoty znaèek klesají ve~smìru od koøene k~listùm a na cestì od koøene k~$x_i$ se -v¹echny bity v $x_i$ na~pozicích urèených znaèkami shodují s bity v $x$. Pøitom -a¾ do~pozice $b$ se shodují i bity znaèkami netestované. Sledujme tuto cestu -od~koøene a¾ po~$b$: pokud cesta odboèuje doprava, jsou v¹echny hodnoty -v~levém podstromu men¹í ne¾~$x$, a~tedy se do~ranku zapoèítají. Pokud odboèuje -doleva, jsou hodnoty v~pravém podstromu zaruèenì vìt¹í a nezapoèítají se. -Pokud nastala neshoda a $xx_i$, tedy celý podstrom je men¹í ne¾ $x$, a~tak je $\rank_X(011001)=4$. +\s{Příklad:} Vezměme množinu $X=\{x_1,x_2,\ldots,x_6\}$ z předchozího příkladu +a počítejme $\rank_X(011001)$. Místo první neshody je označeno puntíkem. +Platí $x>x_i$, tedy celý podstrom je menší než $x$, a~tak je $\rank_X(011001)=4$. -Rádi bychom pøedchozí lemma vyu¾ili k~sestrojení tabulek, které podle uvedených -hodnot vrátí rank prvku~$x$. K~tomu potøebujeme pøedev¹ím umìt indexovat tvarem +Rádi bychom předchozí lemma využili k~sestrojení tabulek, které podle uvedených +hodnot vrátí rank prvku~$x$. K~tomu potřebujeme především umět indexovat tvarem stromu. -\s{Pozorování:} Tvar trie je jednoznaènì urèen hodnotami $c_1,\ldots,c_{r-1}$ -(je to toti¾ kartézský strom nad tìmito hodnotami -- blí¾e viz kapitola o~dekompozicích -stromù), hodnoty v~listech jsou $x_1,\ldots,x_r$ v~poøadí zleva doprava. +\s{Pozorování:} Tvar trie je jednoznačně určen hodnotami $c_1,\ldots,c_{r-1}$ +(je to totiž kartézský strom nad těmito hodnotami -- blíže viz kapitola o~dekompozicích +stromů), hodnoty v~listech jsou $x_1,\ldots,x_r$ v~pořadí zleva doprava. -Kdykoliv chceme indexovat tvarem stromu, mù¾eme místo toho pou¾ít pøimo vektor -$(c_1,\ldots,c_r-1)$, který má $k\log w$ bitù. To se sice u¾ vejde do vektoru, -ale pro indexování tabulek je to stále pøíli¹ (v¹imnìte si, ¾e $\log w$ smí být -vùèi~$k$ libovolnì vysoký -- pro~$w$ známe pouze dolní mez). Proto reprezentaci -je¹tì rozdìlíme na dvì èásti: +Kdykoliv chceme indexovat tvarem stromu, můžeme místo toho použít přimo vektor +$(c_1,\ldots,c_r-1)$, který má $k\log w$ bitů. To se sice už vejde do vektoru, +ale pro indexování tabulek je to stále příliÅ¡ (vÅ¡imněte si, že $\log w$ smí být +vůči~$k$ libovolně vysoký -- pro~$w$ známe pouze dolní mez). Proto reprezentaci +jeÅ¡tě rozdělíme na dvě části: \itemize\ibull -\:$B := \{c_1,\ldots,c_r\}$ (mno¾ina v¹ech pozic bitù, které trie testuje, ulo¾ená ve~vektoru setøídìnì), -\:$C: \{1,\ldots,r\} \to B$ taková, ¾e $B[C(i)]=c_i$. +\:$B := \{c_1,\ldots,c_r\}$ (množina vÅ¡ech pozic bitů, které trie testuje, uložená ve~vektoru setříděně), +\:$C: \{1,\ldots,r\} \to B$ taková, že $B[C(i)]=c_i$. \endlist -\s{Lemma R':} $\rank_X(x)$ lze spoèítat v~konstantním èase~z: +\s{Lemma R':} $\rank_X(x)$ lze spočítat v~konstantním čase~z: \numlist\pnromanap \:funkce $C$, \:hodnot $x_1,\ldots,x_r$, -\:$x[B]$ -- hodnot bitù na~\uv{zajímavých} pozicích v~èísle~$x$. +\:$x[B]$ -- hodnot bitů na~\uv{zajímavých} pozicích v~čísle~$x$. \endlist -\proof Z~pøedchozího lemmatu: +\proof Z~předchozího lemmatu: \numlist\pnromanp -\:Tvar stromu závisí jen na~nerovnostech mezi polohami znaèek, - tak¾e je jednoznaènì urèený funkcí~$C$. -\:Z~tvaru stromu a $x[B]$ jednoznaènì plyne list $x_i$ a tyto vstupy - jsou dostateènì krátké na~to, abychom mohli pøedpoèítat tabulku - pro prùchod stromem. -\:Relaci zjistíme prostým porovnáním, jakmile známe~$x_i$. -\:MSB umíme na~RAMu poèítat v~konstantním èase. +\:Tvar stromu závisí jen na~nerovnostech mezi polohami značek, + takže je jednoznačně určený funkcí~$C$. +\:Z~tvaru stromu a $x[B]$ jednoznačně plyne list $x_i$ a tyto vstupy + jsou dostatečně krátké na~to, abychom mohli předpočítat tabulku + pro průchod stromem. +\:Relaci zjistíme prostým porovnáním, jakmile známe~$x_i$. +\:MSB umíme na~RAMu počítat v~konstantním čase. \endlist -Mezivýsledky (i)--(iv) jsou opìt dost krátké na~to, abychom jimi mohli +Mezivýsledky (i)--(iv) jsou opět dost krátké na~to, abychom jimi mohli indexovat tabulku. \qed -\>Poèítání rankù je témìø v¹e, co potøebujeme k~implementaci operací -\, \ a \. Jedinou dal¹í pøeká¾ku tvoøí zatøiïování -do~seznamu $x_1,\ldots,x_r$, který je moc velký na~to, aby se ve¹el -do~$\O(1)$ slov. Proto si budeme pamatovat zvlá¹» hodnoty v~libovolném -poøadí a zvlá¹» permutaci, která je setøídí -- ta se ji¾ do~vektoru vejde. -Øeknìme tedy poøádnì, co~v¹e si bude struktura pamatovat: +\>Počítání ranků je téměř vÅ¡e, co potřebujeme k~implementaci operací +\, \ a \. Jedinou další překážku tvoří zatřiďování +do~seznamu $x_1,\ldots,x_r$, který je moc velký na~to, aby se veÅ¡el +do~$\O(1)$ slov. Proto si budeme pamatovat zvlášť hodnoty v~libovolném +pořadí a zvlášť permutaci, která je setřídí -- ta se již do~vektoru vejde. +Řekněme tedy pořádně, co~vÅ¡e si bude struktura pamatovat: \s{Stav struktury:} \itemize\ibull -\:$k$, $r$ -- kapacita haldy a aktuální poèet prvkù (èísla), -\:$X=\{x_1,\ldots,x_r\}$ -- hodnoty prvkù v libovolném poøadí (pole èísel), -\:$\varrho$ -- permutace na~$\{1,\ldots,r\}$ taková, ¾e $x_i=X[\varrho(i)]$ +\:$k$, $r$ -- kapacita haldy a aktuální počet prvků (čísla), +\:$X=\{x_1,\ldots,x_r\}$ -- hodnoty prvků v libovolném pořadí (pole čísel), +\:$\varrho$ -- permutace na~$\{1,\ldots,r\}$ taková, že $x_i=X[\varrho(i)]$ a $x_1Nyní ji¾ uká¾eme, jak provádìt jednotlivé operace: +\>Nyní již ukážeme, jak provádět jednotlivé operace: \>$\(x):$ \algo \:$i \leftarrow \rank_X(x)$. -\:Pokud $x_i=x$, odpovíme {\sc ano,} jinak {\sc ne.} +\:Pokud $x_i=x$, odpovíme {\sc ano,} jinak {\sc ne.} \endalgo \>$\(x):$ \algo \:$i \leftarrow \rank_X(x)$. -\:Pokud $x=x_i$, hodnota u¾ je pøítomna. -\:Ulo¾íme $x$ do~$X[\mathop{{+}{+}}r]$ a vlo¾íme $r$ na~$i$-té místo v~permutaci~$\varrho$. -\:Pøepoèítáme $c_{i-1}$ a $c_i$. Pro ka¾dou zmìnu $c_j$: -\::Pokud je¹tì nová hodnota není v~$B$, pøidáme ji tam. -\::Upravíme $C(j)$, aby ukazovalo na~tuto hodnotu. -\::Upravíme ostatní prvky~$C$, ukazující na hodnoty v~$B$, které se vlo¾ením posunuly. -\::Pokud se na~starou hodnotu neodkazuje ¾ádné jiné $C(\cdot)$, sma¾eme ji z~$B$. +\:Pokud $x=x_i$, hodnota už je přítomna. +\:Uložíme $x$ do~$X[\mathop{{+}{+}}r]$ a vložíme $r$ na~$i$-té místo v~permutaci~$\varrho$. +\:Přepočítáme $c_{i-1}$ a $c_i$. Pro každou změnu $c_j$: +\::Pokud jeÅ¡tě nová hodnota není v~$B$, přidáme ji tam. +\::Upravíme $C(j)$, aby ukazovalo na~tuto hodnotu. +\::Upravíme ostatní prvky~$C$, ukazující na hodnoty v~$B$, které se vložením posunuly. +\::Pokud se na~starou hodnotu neodkazuje žádné jiné $C(\cdot)$, smažeme ji z~$B$. \endalgo \>$\(x):$ \algo -\:$i \leftarrow \rank_X(x)$ (víme, ¾e $x_i=x$). -\:Sma¾eme $x_i$ z~pole~$X$ (napøíklad prohozením s~posledním prvkem) a pøíslu¹nì upravíme~$\varrho$. -\:Pøepoèítáme $c_{i-1}$ a $c_i$ a upravíme $B$ a $C$ jako pøi Insertu. +\:$i \leftarrow \rank_X(x)$ (víme, že $x_i=x$). +\:Smažeme $x_i$ z~pole~$X$ (například prohozením s~posledním prvkem) a přísluÅ¡ně upravíme~$\varrho$. +\:Přepočítáme $c_{i-1}$ a $c_i$ a upravíme $B$ a $C$ jako při Insertu. \endalgo -\s{Èasová slo¾itost:} V¹echny kroky operací po~výpoètu ranku trvají konstantní èas, rank -samotný zvládneme spoèítat v~$\O(1)$ pomocí tabulek, pokud známe $x[B]$. Zde je ov¹em -nalíèen háèek -- tuto operaci nelze na~Word-RAMu konstantním poètem instrukcí spoèítat. -Pomoci si mù¾eme dvìma zpùsoby: +\s{Časová složitost:} VÅ¡echny kroky operací po~výpočtu ranku trvají konstantní čas, rank +samotný zvládneme spočítat v~$\O(1)$ pomocí tabulek, pokud známe $x[B]$. Zde je ovÅ¡em +nalíčen háček -- tuto operaci nelze na~Word-RAMu konstantním počtem instrukcí spočítat. +Pomoci si můžeme dvěma způsoby: \numlist\nalpha -\:Vyu¾ijeme toho, ¾e operace $x[B]$ je v~${\rm AC}^0$, a vystaèíme si se strukturou pro ${\rm AC}^0$-RAM. -Zde dokonce mù¾eme vytváøet haldy velikosti a¾ $w\log w$. Také pøi praktické implementaci mù¾eme vyu¾ít -toho, ¾e souèasné procesory mají instrukce na~spoustu zajímavých ${\rm AC}^0$-operací, viz napø. pìkný +\:Využijeme toho, že operace $x[B]$ je v~${\rm AC}^0$, a vystačíme si se strukturou pro ${\rm AC}^0$-RAM. +Zde dokonce můžeme vytvářet haldy velikosti až $w\log w$. Také při praktické implementaci můžeme využít +toho, že současné procesory mají instrukce na~spoustu zajímavých ${\rm AC}^0$-operací, viz např. pěkný rozbor v \cite{thorup:ac0}. -\:Jeliko¾ $B$ se pøi jedné Q-Heapové operaci mìní pouze o~konstantní poèet prvkù, mù¾eme -si udr¾ovat pomocné struktury, které budeme umìt pøi lokální zmìnì~$B$ v~lineárním èase -pøepoèítat a pak pomocí nich indexovat. To pomocí Word-RAMu lze zaøídit, ale je to technicky -dosti nároèné, tak¾e ètenáøe zvìdavého na~detaily odkazujeme na~èlánek \cite{fw90trans}. +\:Jelikož $B$ se při jedné Q-Heapové operaci mění pouze o~konstantní počet prvků, můžeme +si udržovat pomocné struktury, které budeme umět při lokální změně~$B$ v~lineárním čase +přepočítat a pak pomocí nich indexovat. To pomocí Word-RAMu lze zařídit, ale je to technicky +dosti náročné, takže čtenáře zvědavého na~detaily odkazujeme na~článek \cite{fw90trans}. \endlist -\h{Aplikace Q-Heapù} +\h{Aplikace Q-Heapů} -Jedním velice pìkným dùsledkem existence Q-Heapù je lineární algoritmus na~nalezení -minimální kostry grafu ohodnoceného celými èísly. Získáme ho z~Fredmanovy a Tarjanovy -varianty Jarníkova algoritmu (viz kapitoly o~kostrách) tak, ¾e v~první iteraci pou¾ijeme -jako haldu Q-Heap velikosti $\log^{1/4} n$ a pak budeme pokraèovat s~pùvodní Fibonacciho -haldou. Tak provedeme tolik prùchodù, kolikrát je potøeba zlogaritmovat $n$, -aby výsledek klesl pod~$\log^{1/4} n$, a~to je konstanta. V¹imnìte si, ¾e by nám -dokonce staèila halda velikosti $\Omega(\log^{(k)} n)$ s~operacemi v~konstantním èase -pro nìjaké libovolné~$k$. +Jedním velice pěkným důsledkem existence Q-Heapů je lineární algoritmus na~nalezení +minimální kostry grafu ohodnoceného celými čísly. Získáme ho z~Fredmanovy a Tarjanovy +varianty Jarníkova algoritmu (viz kapitoly o~kostrách) tak, že v~první iteraci použijeme +jako haldu Q-Heap velikosti $\log^{1/4} n$ a pak budeme pokračovat s~původní Fibonacciho +haldou. Tak provedeme tolik průchodů, kolikrát je potřeba zlogaritmovat $n$, +aby výsledek klesl pod~$\log^{1/4} n$, a~to je konstanta. VÅ¡imněte si, že by nám +dokonce stačila halda velikosti $\Omega(\log^{(k)} n)$ s~operacemi v~konstantním čase +pro nějaké libovolné~$k$. \references \bye diff --git a/9-decomp/9-decomp.tex b/9-decomp/9-decomp.tex index 03a9209..9b6e53e 100644 --- a/9-decomp/9-decomp.tex +++ b/9-decomp/9-decomp.tex @@ -1,131 +1,131 @@ \input ../sgr.tex -\hyphenation{mikro-strom mikro-stro-mo-vé} +\hyphenation{mikro-strom mikro-stro-mo-vé} -\prednaska{9}{Dekompozice stromù}{} +\prednaska{9}{Dekompozice stromů}{} -V~této kapitole uká¾eme nìkolik datových struktur zalo¾ených -na~my¹lence dekompozice problému na~dostateènì malé podproblémy, -které u¾ umíme (obvykle vhodným kódováním èísly) øe¹it v~konstantním -èase. +V~této kapitole ukážeme několik datových struktur založených +na~myÅ¡lence dekompozice problému na~dostatečně malé podproblémy, +které už umíme (obvykle vhodným kódováním čísly) řeÅ¡it v~konstantním +čase. \h{Union-Find Problem} -\s{Problém:} Udr¾ování tøíd ekvivalence: na~poèátku máme $N$ jednoprvkových ekvivalenèních -tøíd, provádíme operace \ (zji¹tìní, zda dva prvky jsou ekvivalentní) a \ -(slouèení dvou tøíd do~jedné). Také na~to lze pohlí¾et jako na~inkrementální udr¾ování -komponent souvislosti neorientovaného grafu: \ je pøidání hrany, \ test, -zda dva vrcholy le¾í v~té¾e komponentì. To se hodí v~mnoha algoritmech, kupøíkladu -v~Kruskalovì algoritmu pro hledání minimální kostry. - -\s{Triviální øe¹ení:} Prvky ka¾dé tøídy obarvíme unikátní barvou (identifikátorem -tøídy). Operace \ porovnává barvy, \ prvky jedné ze~sjednocovaných -tøíd pøebarvuje. - -Operace \ tak pracuje v~konstantním èase, \ mù¾e zabrat a¾ lineární èas. Mù¾eme si -pomoci tím, ¾e v¾dy pøebarvíme {\I men¹í} ze~sluèovaných ekvivalenèních tøíd (budeme -si pro ka¾dou tøídu pamatovat seznam jejích prvkù a velikost). Tehdy mù¾e být ka¾dý -prvek pøebarven jen $\O(\log n)$-krát, jeliko¾ ka¾dým pøebarvením se alespoò zdvojnásobí -velikost tøídy, ve~které prvek le¾í. Posloupnost operací \, kterou vznikla tøída -velikosti~$k$, tak trvá $\O(k\log k)$, tak¾e mù¾eme bezpeènì prohlásit, ¾e amortizovaná -slo¾itost operace \ je $\O(\log n)$. - -\s{Chytøej¹í øe¹ení:} Ka¾dou tøídu budeme reprezentovat zakoøenìným stromem s~hranami -orientovanými smìrem ke~koøeni (jinými slovy pro ka¾dý prvek si pamatujeme jeho otce -nebo ¾e je to koøen). \ nalezne koøeny stromù a porovná je, \ pøipojí koøen -jedné tøídy pod koøen druhé. Aby stromy nedegenerovaly, pøidáme dvì pravidla: +\s{Problém:} Udržování tříd ekvivalence: na~počátku máme $N$ jednoprvkových ekvivalenčních +tříd, provádíme operace \ (zjiÅ¡tění, zda dva prvky jsou ekvivalentní) a \ +(sloučení dvou tříd do~jedné). Také na~to lze pohlížet jako na~inkrementální udržování +komponent souvislosti neorientovaného grafu: \ je přidání hrany, \ test, +zda dva vrcholy leží v~téže komponentě. To se hodí v~mnoha algoritmech, kupříkladu +v~Kruskalově algoritmu pro hledání minimální kostry. + +\s{Triviální řeÅ¡ení:} Prvky každé třídy obarvíme unikátní barvou (identifikátorem +třídy). Operace \ porovnává barvy, \ prvky jedné ze~sjednocovaných +tříd přebarvuje. + +Operace \ tak pracuje v~konstantním čase, \ může zabrat až lineární čas. Můžeme si +pomoci tím, že vždy přebarvíme {\I menší} ze~slučovaných ekvivalenčních tříd (budeme +si pro každou třídu pamatovat seznam jejích prvků a velikost). Tehdy může být každý +prvek přebarven jen $\O(\log n)$-krát, jelikož každým přebarvením se alespoň zdvojnásobí +velikost třídy, ve~které prvek leží. Posloupnost operací \, kterou vznikla třída +velikosti~$k$, tak trvá $\O(k\log k)$, takže můžeme bezpečně prohlásit, že amortizovaná +složitost operace \ je $\O(\log n)$. + +\s{Chytřejší řeÅ¡ení:} Každou třídu budeme reprezentovat zakořeněným stromem s~hranami +orientovanými směrem ke~kořeni (jinými slovy pro každý prvek si pamatujeme jeho otce +nebo že je to kořen). \ nalezne kořeny stromů a porovná je, \ připojí kořen +jedné třídy pod kořen druhé. Aby stromy nedegenerovaly, přidáme dvě pravidla: \itemize\ibull -\:{\I Union dle ranku:} ka¾dý koøen $v$ si bude pamatuje svùj rank $r(v)$, co¾ je nìjaké -pøirozené èíslo. Na~poèátku jsou v¹echny ranky nulové. Pokud spojujeme -dva stromy s~koøeny $v$, $w$ a $r(v)), pøepojíme v¹echny vrcholy na~cestì, po~které jsme pro¹li, -rovnou pod koøen. +\:{\I Union dle ranku:} každý kořen $v$ si bude pamatuje svůj rank $r(v)$, což je nějaké +přirozené číslo. Na~počátku jsou vÅ¡echny ranky nulové. Pokud spojujeme +dva stromy s~kořeny $v$, $w$ a $r(v)), přepojíme vÅ¡echny vrcholy na~cestě, po~které jsme proÅ¡li, +rovnou pod kořen. \endlist -Pro úèely analýzy struktury budeme uva¾ovat také ranky ostatních vrcholù -- ka¾dý vrchol -si ponese svùj rank z~doby, kdy byl naposledy koøenem. Struktura se ov¹em -podle rankù vnitøních vrcholù nijak neøídí a nemusí si je ani pamatovat. -Stromu s~koøenem ranku~$r$ budeme zkrácenì øíkat {\I strom ranku~$r$.} +Pro účely analýzy struktury budeme uvažovat také ranky ostatních vrcholů -- každý vrchol +si ponese svůj rank z~doby, kdy byl naposledy kořenem. Struktura se ovÅ¡em +podle ranků vnitřních vrcholů nijak neřídí a nemusí si je ani pamatovat. +Stromu s~kořenem ranku~$r$ budeme zkráceně říkat {\I strom ranku~$r$.} -\s{Invariant~C:} Na ka¾dé cestì z~vrcholu do~koøene pøíslu¹ného stromu ranky -ostøe rostou. Jinými slovy rank vrcholu, který není koøen, je men¹í, ne¾ je rank +\s{Invariant~C:} Na každé cestě z~vrcholu do~kořene přísluÅ¡ného stromu ranky +ostře rostou. Jinými slovy rank vrcholu, který není kořen, je menší, než je rank jeho otce. \proof -Na poèátku (pro jednovrcholové stromy) tvrzení jistì platí. -Nech» provedeme Union, který pøipojí vrchol~$v$ pod~$w$. Cesty do~koøene z~vrcholù, -které le¾ely pod~$w$, zùstanou zachovány, pouze se vrcholu~$w$ pøípadnì -zvý¹í rank. Cesty z~vrcholù pod~$v$ se roz¹íøí o~hranu~$vw$, na které rank -v~ka¾dém pøípadì roste. -Komprese cest nahrazuje otce vrcholu jeho vzdálenìj¹ím pøedkem, tak¾e se rank -otce mù¾e jedinì zvý¹it. +Na počátku (pro jednovrcholové stromy) tvrzení jistě platí. +NechÅ¥ provedeme Union, který připojí vrchol~$v$ pod~$w$. Cesty do~kořene z~vrcholů, +které ležely pod~$w$, zůstanou zachovány, pouze se vrcholu~$w$ případně +zvýší rank. Cesty z~vrcholů pod~$v$ se rozšíří o~hranu~$vw$, na které rank +v~každém případě roste. +Komprese cest nahrazuje otce vrcholu jeho vzdálenějším předkem, takže se rank +otce může jedině zvýšit. \qed -\s{Invariant~R:} Strom ranku~$r$ obsahuje alespoò $2^r$ vrcholù. +\s{Invariant~R:} Strom ranku~$r$ obsahuje alespoň $2^r$ vrcholů. \proof -Indukcí podle èasu. Pro jednovrcholové stromy o~nulovém ranku tvrzení platí. -Nech» pøipojíme vrchol~$v$ pod vrchol~$w$. Je-li $r(v) a \. +\s{Důsledek:} Rank každého stromu je $\O(\log n)$, takže rank každého vnitřního +vrcholu taktéž. Díky invariantu~C strávíme výstupem z~každého vrcholu do~kořene +také čas $\O(\log n)$, takže logaritmická je i složitost operací \ a \. -K~tomu nám ov¹em staèilo samotné pravidlo Union podle ranku, o~kompresi cest -jsme zatím dokázali pouze to, ¾e slo¾itost v~nejhor¹ím pøípadì nezhor¹uje.% -\foot{Mimochodem, Komprese cest samotná by také na~slo¾itost $\O(\log n)$ amortizovanì staèila \cite{tarjan84setunion}.} -Kombinace obou metod se ve~skuteènosti chová mnohem lépe: +K~tomu nám ovÅ¡em stačilo samotné pravidlo Union podle ranku, o~kompresi cest +jsme zatím dokázali pouze to, že složitost v~nejhorším případě nezhorÅ¡uje.% +\foot{Mimochodem, Komprese cest samotná by také na~složitost $\O(\log n)$ amortizovaně stačila \cite{tarjan84setunion}.} +Kombinace obou metod se ve~skutečnosti chová mnohem lépe: -\s{Vìta:} (Tarjan, van Leeuwen \cite{tarjan84setunion}) -Posloupnost $m$~operací \ a \ provedená na~prázdné struktuøe s~$n$ vrcholy -trvá $\O(n + m\alpha(m,n))$, kde $\alpha$ je inverzní Ackermannova funkce.% -\foot{Je známo \cite{fredman:cellprobe}, ¾e asymptoticky lep¹í slo¾itosti nelze dosáhnout, -a~to ani v~modelu silnìj¹ím ne¾ RAM. Námi uvádìný algoritmus si témìø vystaèí -s~Pointer Machine, jen porovnávání rankù z~tohoto modelu vyboèuje. Slo¾itost -operací v~nejhor¹ím pøípadì je obecnì hor¹í, je znám dolní odhad $\Omega(\log n/\log\log n)$; -více viz Alstrup \cite{alstrup:worstuf}.} +\s{Věta:} (Tarjan, van Leeuwen \cite{tarjan84setunion}) +Posloupnost $m$~operací \ a \ provedená na~prázdné struktuře s~$n$ vrcholy +trvá $\O(n + m\alpha(m,n))$, kde $\alpha$ je inverzní Ackermannova funkce.% +\foot{Je známo \cite{fredman:cellprobe}, že asymptoticky lepší složitosti nelze dosáhnout, +a~to ani v~modelu silnějším než RAM. Námi uváděný algoritmus si téměř vystačí +s~Pointer Machine, jen porovnávání ranků z~tohoto modelu vybočuje. Složitost +operací v~nejhorším případě je obecně horší, je znám dolní odhad $\Omega(\log n/\log\log n)$; +více viz Alstrup \cite{alstrup:worstuf}.} -Dùkaz této vìty neuvádíme, jeliko¾ je technicky dosti nároèný. Místo toho podobnou -metodou uká¾eme trochu slab¹í výsledek s~iterovaným logaritmem: +Důkaz této věty neuvádíme, jelikož je technicky dosti náročný. Místo toho podobnou +metodou ukážeme trochu slabší výsledek s~iterovaným logaritmem: -\s{Vìta':} Ve~struktuøe s~$n$ prvky trvá provedení posloupnosti $m$~operací +\s{Věta':} Ve~struktuře s~$n$ prvky trvá provedení posloupnosti $m$~operací \ a \ $\O((n+m)\cdot\log^* n)$. \def\up{\mathop{\uparrow}} -\s{Definice:} {\I Vì¾ovou funkci} $2\up k$ definujeme následovnì: $2\up 0=1$, +\s{Definice:} {\I Věžovou funkci} $2\up k$ definujeme následovně: $2\up 0=1$, $2\up (k+1)=2^{2\up k}$. -Funkce $2\up k$ je tedy $k$-krát iterovaná mocnina dvojky a $\log^*$ je funkce -k~této funkci inverzní. +Funkce $2\up k$ je tedy $k$-krát iterovaná mocnina dvojky a $\log^*$ je funkce +k~této funkci inverzní. -Vrcholy ve~struktuøe si nyní rozdìlíme podle jejich rankù: -$k$-tá skupina bude tvoøena tìmi vrcholy, jejich¾ rank je od~$2\up (k-1)+1$ do~$2\up k$. Vrcholy jsou -tedy rozdìleny do~$1+\log^*\log n$ skupin. Odhadnìme nyní shora poèet vrcholù v~$k$-té -skupinì. +Vrcholy ve~struktuře si nyní rozdělíme podle jejich ranků: +$k$-tá skupina bude tvořena těmi vrcholy, jejichž rank je od~$2\up (k-1)+1$ do~$2\up k$. Vrcholy jsou +tedy rozděleny do~$1+\log^*\log n$ skupin. Odhadněme nyní shora počet vrcholů v~$k$-té +skupině. -\s{Invariant~S:} V~$k$-té skupinì le¾í nejvý¹e $n/(2\up k)$ vrcholù. +\s{Invariant~S:} V~$k$-té skupině leží nejvýše $n/(2\up k)$ vrcholů. \proof -Nejprve uká¾eme, ¾e vrcholù s~rankem~$r$ je nejvý¹e $n/2^r$. Kdybychom nekomprimovali -cesty, snadno to plyne z~invariantù~C a~R: ka¾dému vrcholu ranku~$r$ pøiøadíme v¹ech -jeho alespoò $2^r$ potomkù. Jeliko¾ ranky na cestách smìrem ke~koøeni rostou, ¾ádného -potomka jsme nemohli pøiøadit více vrcholùm. Komprese cest ov¹em nemù¾e invariant -poru¹it, proto¾e nemìní ranky ani rozhodnutí, jak probìhne který \. +Nejprve ukážeme, že vrcholů s~rankem~$r$ je nejvýše $n/2^r$. Kdybychom nekomprimovali +cesty, snadno to plyne z~invariantů~C a~R: každému vrcholu ranku~$r$ přiřadíme vÅ¡ech +jeho alespoň $2^r$ potomků. Jelikož ranky na cestách směrem ke~kořeni rostou, žádného +potomka jsme nemohli přiřadit více vrcholům. Komprese cest ovÅ¡em nemůže invariant +poruÅ¡it, protože nemění ranky ani rozhodnutí, jak proběhne který \. -Teï u¾ staèí odhad $n/2^r$ seèíst pøes v¹echny ranky ve~skupinì: +Teď už stačí odhad $n/2^r$ sečíst přes vÅ¡echny ranky ve~skupině: $$ {n \over 2^{2\up(k-1)+1}} + {n \over 2^{2\up(k-1)+2}} + \cdots + {n \over 2^{2\up k}} \le {n \over 2^{2\up(k-1)}} \cdot \sum_{i=1}^\infty {1 \over 2^i} = @@ -134,363 +134,363 @@ $$ $$ \qed -\>{\sl Dùkaz vìty:} -Operace \ a \ potøebují nekonstantní èas pouze na~vystoupání -po~cestì ze~zadaného vrcholu~$v$ do~koøene stromu. Èas strávený na~této cestì -je pøímo úmìrný poètu hran cesty. Celá cesta je pøitom rozpojena a v¹echny -vrcholy le¾ící na~ní jsou pøepojeny pøímo pod~koøen stromu. - -Hrany cesty, které spojují vrcholy z~rùzných skupin (takových je $\O(\log^* n)$), -naúètujeme právì provádìné operaci. Celkem jimi tedy strávíme èas $\O(m\log^*n)$. -Zbylé hrany budeme poèítat pøes celou dobu bìhu algoritmu a úètovat je vrcholùm. - -Uva¾me vrchol~$v$ v~$k$-té skupinì, jeho¾ rodiè le¾í také v~$k$-té skupinì. -Jeliko¾ hrany na cestách do~koøene ostøe rostou, ka¾dým pøepojením vrcholu~$v$ rank jeho -rodièe vzroste. Proto po nejvý¹e $2\up k$ pøepojeních se bude rodiè vrcholu~$v$ nacházet -v~nìkteré z~vy¹¹ích skupin. Jeliko¾ rank vrcholu~$v$ se u¾ nikdy nezmìní, bude hrana z~$v$ -do~jeho otce ji¾ nav¾dy hranou mezi skupinami. Ka¾dému vrcholu v~$k$-té skupinì tedy naúètujeme -nejvý¹e $2\up k$ pøepojení a jeliko¾, jak u¾ víme, jeho skupina obsahuje nejvý¹e $n/(2\up k)$ vrcholù, -naúètujeme celé skupinì èas $\O(n)$ a v¹em skupinám dohromady $\O(n\log^* n)$. +\>{\sl Důkaz věty:} +Operace \ a \ potřebují nekonstantní čas pouze na~vystoupání +po~cestě ze~zadaného vrcholu~$v$ do~kořene stromu. Čas strávený na~této cestě +je přímo úměrný počtu hran cesty. Celá cesta je přitom rozpojena a vÅ¡echny +vrcholy ležící na~ní jsou přepojeny přímo pod~kořen stromu. + +Hrany cesty, které spojují vrcholy z~různých skupin (takových je $\O(\log^* n)$), +naúčtujeme právě prováděné operaci. Celkem jimi tedy strávíme čas $\O(m\log^*n)$. +Zbylé hrany budeme počítat přes celou dobu běhu algoritmu a účtovat je vrcholům. + +Uvažme vrchol~$v$ v~$k$-té skupině, jehož rodič leží také v~$k$-té skupině. +Jelikož hrany na cestách do~kořene ostře rostou, každým přepojením vrcholu~$v$ rank jeho +rodiče vzroste. Proto po nejvýše $2\up k$ přepojeních se bude rodič vrcholu~$v$ nacházet +v~některé z~vyšších skupin. Jelikož rank vrcholu~$v$ se už nikdy nezmění, bude hrana z~$v$ +do~jeho otce již navždy hranou mezi skupinami. Každému vrcholu v~$k$-té skupině tedy naúčtujeme +nejvýše $2\up k$ přepojení a jelikož, jak už víme, jeho skupina obsahuje nejvýše $n/(2\up k)$ vrcholů, +naúčtujeme celé skupině čas $\O(n)$ a vÅ¡em skupinám dohromady $\O(n\log^* n)$. \qed -\h{Union-Find s~pøedem známými Uniony} +\h{Union-Find s~předem známými Uniony} -Dále nás bude zajímat speciální varianta Union-Find problému, v~ní¾ dopøedu známe -posloupnost Unionù, èili strom, který spojováním komponent vznikne.\foot{Kdy se to hodí? -Tøeba v~Thorupovì lineárním algoritmu \cite{thorup:usssp} na~nejkrat¹í cesty nebo -ve~Weiheho takté¾ lineárním algoritmu \cite{weihe:paths} na~hledání hranovì disjunktních -cest v~rovinných grafech.} -Jiná interpretace tého¾ (jen pozpátku) je dekrementální udr¾ování komponent -souvislosti lesa: na~poèátku je dán les, umíme smazat hranu a otestovat, zda jsou -dva vrcholy v~tém¾e stromu. +Dále nás bude zajímat speciální varianta Union-Find problému, v~níž dopředu známe +posloupnost Unionů, čili strom, který spojováním komponent vznikne.\foot{Kdy se to hodí? +Třeba v~Thorupově lineárním algoritmu \cite{thorup:usssp} na~nejkratší cesty nebo +ve~Weiheho taktéž lineárním algoritmu \cite{weihe:paths} na~hledání hranově disjunktních +cest v~rovinných grafech.} +Jiná interpretace téhož (jen pozpátku) je dekrementální udržování komponent +souvislosti lesa: na~počátku je dán les, umíme smazat hranu a otestovat, zda jsou +dva vrcholy v~témže stromu. -Popí¹eme algoritmus, -který po~poèáteèním pøedzpracování v~èase $\O(n)$ zvládne \ i \ v~amortizovanì -konstantním èase. Tento algoritmus je kombinací dekompozic popsaných Alstrupem \cite{alstrup97optimal,alstrup98marked}. +Popíšeme algoritmus, +který po~počátečním předzpracování v~čase $\O(n)$ zvládne \ i \ v~amortizovaně +konstantním čase. Tento algoritmus je kombinací dekompozic popsaných Alstrupem \cite{alstrup97optimal,alstrup98marked}. -\s{Definice:} {\I (Microtree/Macrotree dekompozice)} Pro zakoøenìný strom $T$ o~$n$ vrcholech +\s{Definice:} {\I (Microtree/Macrotree dekompozice)} Pro zakořeněný strom $T$ o~$n$ vrcholech definujeme: \itemize\ibull -\:{\I Koøeny mikrostromù} budou nejvy¹¹í vrcholy v~$T$, pod~nimi¾ je nejvý¹e $\log n$ listù -a které nejsou koøenem celého~$T$. -\:{\I Mikrostromy} le¾í v~$T$ od~tìchto koøenù ní¾e. -\:{\I Spojovací hrany} vedou z~koøenù mikrostromù do~jejich otcù. -\:{\I Makrostrom} je tvoøen zbývajícími vrcholy a hranami stromu~$T$. +\:{\I Kořeny mikrostromů} budou nejvyšší vrcholy v~$T$, pod~nimiž je nejvýše $\log n$ listů +a které nejsou kořenem celého~$T$. +\:{\I Mikrostromy} leží v~$T$ od~těchto kořenů níže. +\:{\I Spojovací hrany} vedou z~kořenů mikrostromů do~jejich otců. +\:{\I Makrostrom} je tvořen zbývajícími vrcholy a hranami stromu~$T$. \endlist -\s{Pozorování:} Ka¾dý mikrostrom má nejvý¹e $\log n$ listù. Pod ka¾dým listem makrostromu le¾í -alespoò jeden mikrostrom (mù¾e jich být i více, viz dekompozice hvìzdy na~obrázku), tak¾e -listù makrostromu je nejvý¹e $n/\log n$. +\s{Pozorování:} Každý mikrostrom má nejvýše $\log n$ listů. Pod každým listem makrostromu leží +alespoň jeden mikrostrom (může jich být i více, viz dekompozice hvězdy na~obrázku), takže +listů makrostromu je nejvýše $n/\log n$. -Vnitøních vrcholù makro- i mikrostromù ale mù¾e být ne¹ikovnì mnoho, proto¾e se ve~stromech mohou -vyskytovat dlouhé cesty. Pomù¾eme si snadno: ka¾dou cestu si budeme pamatovat zvlá¹» a ve~stromu -ji nahradíme hranou, která bude vlo¾ena právì tehdy, kdy¾ budou pøítomny v¹echny hrany cesty. +Vnitřních vrcholů makro- i mikrostromů ale může být neÅ¡ikovně mnoho, protože se ve~stromech mohou +vyskytovat dlouhé cesty. Pomůžeme si snadno: každou cestu si budeme pamatovat zvlášť a ve~stromu +ji nahradíme hranou, která bude vložena právě tehdy, když budou přítomny vÅ¡echny hrany cesty. -\s{Pøíklad:} Následující obrázek ukazuje dekompozici nìkolika stromù za~pøedpokladu, -¾e $\log n=4$. Vrcholy mikrostromù jsou èerné, makrostromu bílé. Spojovací hrany kreslíme teèkovanì, -hrany komprimovaných cest tuènì. +\s{Příklad:} Následující obrázek ukazuje dekompozici několika stromů za~předpokladu, +že $\log n=4$. Vrcholy mikrostromů jsou černé, makrostromu bílé. Spojovací hrany kreslíme tečkovaně, +hrany komprimovaných cest tučně. \medskip \fig{mima.eps}{\epsfxsize} -\s{Algoritmus pro cesty:} Cestu délky~$l$ rozdìlíme na~úseky délky $\log n$, pro nì¾ si ulo¾íme -mno¾iny ji¾ pøítomných hran (po~bitech jako èísla). Pak si je¹tì pamatujeme zkomprimovanou cestu (hrany -odpovídají úsekùm a jsou pøítomny právì tehdy, jsou-li pøítomny v¹echny hrany pøíslu¹ného úseku) -délky $l/\log n$ a pro ni \uv{pøebarvovací} strukturu pro Union-Find. +\s{Algoritmus pro cesty:} Cestu délky~$l$ rozdělíme na~úseky délky $\log n$, pro něž si uložíme +množiny již přítomných hran (po~bitech jako čísla). Pak si jeÅ¡tě pamatujeme zkomprimovanou cestu (hrany +odpovídají úsekům a jsou přítomny právě tehdy, jsou-li přítomny vÅ¡echny hrany přísluÅ¡ného úseku) +délky $l/\log n$ a pro ni \uv{přebarvovací} strukturu pro Union-Find. -\>$\(x,y)$ (pøidání hrany $e=xy$ do~cesty): +\>$\(x,y)$ (přidání hrany $e=xy$ do~cesty): \algo -\:Pøidáme $e$ do mno¾iny hran pøítomných v~pøíslu¹ném úseku. -\:Pokud se tím úsek naplnil, pøidáme odpovídající hranu do~zkomprimované cesty. +\:Přidáme $e$ do množiny hran přítomných v~přísluÅ¡ném úseku. +\:Pokud se tím úsek naplnil, přidáme odpovídající hranu do~zkomprimované cesty. \endalgo \>$\(x,y):$ \algo -\:Pokud $x$ a $y$ jsou v~tém¾e úseku, otestujeme bitovými operacemi, zda - jsou v¹echny hrany mezi $x$ a $y$ pøítomny. -\:Pokud jsou v~rùzných úsecích, rozdìlíme cestu z~$x$ do~$y$ na~posloupnost celých úsekù, - na~které nám odpoví zkomprimovaná cesta, a~dva dotazy v~krajních èásteèných úsecích. +\:Pokud $x$ a $y$ jsou v~témže úseku, otestujeme bitovými operacemi, zda + jsou vÅ¡echny hrany mezi $x$ a $y$ přítomny. +\:Pokud jsou v~různých úsecích, rozdělíme cestu z~$x$ do~$y$ na~posloupnost celých úseků, + na~které nám odpoví zkomprimovaná cesta, a~dva dotazy v~krajních částečných úsecích. \endalgo -Operace uvnitø úsekù pracují v~èase $\O(1)$, operace na~zkomprimované cestì v~$\O(\log l)$ -amortizovanì, ale za~dobu ¾ivota struktury je jich $\O(l/\log n)=\O(l/\log l)$, tak¾e celkovì zaberou lineární èas. +Operace uvnitř úseků pracují v~čase $\O(1)$, operace na~zkomprimované cestě v~$\O(\log l)$ +amortizovaně, ale za~dobu života struktury je jich $\O(l/\log n)=\O(l/\log l)$, takže celkově zaberou lineární čas. -\s{Komprese cest:} Operace na~mikro/makro-stromech budeme následujícím zpùsobem -pøevádìt na~operace s~jejich cestovì komprimovanými podobami a na~operace s~cestovými strukturami: +\s{Komprese cest:} Operace na~mikro/makro-stromech budeme následujícím způsobem +převádět na~operace s~jejich cestově komprimovanými podobami a na~operace s~cestovými strukturami: \>$\(x,y)$: \algo -\:Pokud $e=xy$ le¾í uvnitø nìjaké cesty, pøidáme ji do~cesty, co¾ buïto zpùsobí - pøidávání jiné hrany, a~nebo u¾ jsme hotovi. -\:Provedeme \ v~komprimovaném stromu. +\:Pokud $e=xy$ leží uvnitř nějaké cesty, přidáme ji do~cesty, což buďto způsobí + přidávání jiné hrany, a~nebo už jsme hotovi. +\:Provedeme \ v~komprimovaném stromu. \endalgo \>$\(x,y)$: \algo -\:Pokud $x$ a $y$ le¾í uvnitø jedné cesty, zeptáme se cestové struktury a konèíme. -\:Pokud $x$ le¾í uvnitø nìjaké cesty, zjistíme dotazem na~cestovou strukturu, - ke~kterému krajnímu vrcholu cesty je pøipojen, a~$x$ nahradíme tímto vrcholem. - Není-li pøipojen k~¾ádnému, je~evidentnì odpovìï na~celý \ negativní; - pokud k~obìma, vybereme si libovolný, proto¾e jsou stejnì v~cestovì komprimovaném +\:Pokud $x$ a $y$ leží uvnitř jedné cesty, zeptáme se cestové struktury a končíme. +\:Pokud $x$ leží uvnitř nějaké cesty, zjistíme dotazem na~cestovou strukturu, + ke~kterému krajnímu vrcholu cesty je připojen, a~$x$ nahradíme tímto vrcholem. + Není-li připojen k~žádnému, je~evidentně odpověď na~celý \ negativní; + pokud k~oběma, vybereme si libovolný, protože jsou stejně v~cestově komprimovaném stromu spojeny hranou. Analogicky pro~$y$. -\:Zeptáme se struktury pro komprimovaný strom. +\:Zeptáme se struktury pro komprimovaný strom. \endalgo -\s{Algoritmus pro mikrostromy:} Po~kompresi cest má ka¾dý mikrostrom nejvý¹e $2\log n$ -vrcholù, èili také nejvý¹e tolik hran. Hrany si oèíslujeme pøirozenými èísly, ka¾dou -mno¾inu hran pak mù¾eme reprezentovat $(2\log n)$-bitovým èíslem a mno¾inové operace -provádìt pomocí bitových v~konstantním èase. +\s{Algoritmus pro mikrostromy:} Po~kompresi cest má každý mikrostrom nejvýše $2\log n$ +vrcholů, čili také nejvýše tolik hran. Hrany si očíslujeme přirozenými čísly, každou +množinu hran pak můžeme reprezentovat $(2\log n)$-bitovým číslem a množinové operace +provádět pomocí bitových v~konstantním čase. -Pro ka¾dý mikrostrom si pøedpoèítáme pro v¹echny jeho vrcholy~$v$ mno¾iny~$P_v$ hran le¾ících -na~cestì z~koøene mikrostromu do~$v$. Navíc si budeme pro celý mikrostrom pamatovat mno¾inu -pøítomných hran~$F$. +Pro každý mikrostrom si předpočítáme pro vÅ¡echny jeho vrcholy~$v$ množiny~$P_v$ hran ležících +na~cestě z~kořene mikrostromu do~$v$. Navíc si budeme pro celý mikrostrom pamatovat množinu +přítomných hran~$F$. \>$\(x,y):$ \algo -\:Najdeme poøadové èíslo $i$ hrany $xy$ (máme pøedpoèítané). +\:Najdeme pořadové číslo $i$ hrany $xy$ (máme předpočítané). \:$F \leftarrow F \cup \{i\}$. \endalgo \>$\(x,y):$ \algo -\:$P \leftarrow P_x \mathop{\Delta} P_y$ (mno¾ina hran le¾ících na~cestì z~$x$ do~$y$). -\:Pokud $P\setminus F=\emptyset$, le¾í $x$ a $y$ ve~stejnì komponentì, jinak ne. +\:$P \leftarrow P_x \mathop{\Delta} P_y$ (množina hran ležících na~cestě z~$x$ do~$y$). +\:Pokud $P\setminus F=\emptyset$, leží $x$ a $y$ ve~stejně komponentě, jinak ne. \endalgo -\s{Algoritmus pro celý problém:} Strom rozlo¾íme na~mikrostromy, makrostrom a spojovací -hrany. V~mikrostromech i makrostromu zkomprimujeme cesty. Pro cesty a mikrostromy pou¾ijeme -vý¹e popsané struktury, pro ka¾dou spojovací hranu si budeme pamatovat jen znaèku, -zda je pøítomna, a pro makrostrom pøebarvovací strukturu. +\s{Algoritmus pro celý problém:} Strom rozložíme na~mikrostromy, makrostrom a spojovací +hrany. V~mikrostromech i makrostromu zkomprimujeme cesty. Pro cesty a mikrostromy použijeme +výše popsané struktury, pro každou spojovací hranu si budeme pamatovat jen značku, +zda je přítomna, a pro makrostrom přebarvovací strukturu. \>$\(x,y)$: \algo -\:Pokud $e=xy$ je spojovací, poznamenáme si, ¾e je pøítomna, a~konèíme. -\:Nyní víme, ¾e $e$ le¾í uvnitø mikrostromu nebo makrostromu, a~tak provedeme \ - na~pøíslu¹né struktuøe. +\:Pokud $e=xy$ je spojovací, poznamenáme si, že je přítomna, a~končíme. +\:Nyní víme, že $e$ leží uvnitř mikrostromu nebo makrostromu, a~tak provedeme \ + na~přísluÅ¡né struktuře. \endlist \>$\(x,y)$: \algo -\:Le¾í-li $x$ a $y$ v~jednom mikrostromu, zeptáme se struktury pro~mikrostrom. -\:Je-li $x$ uvnitø mikrostromu, zeptáme se mikrostruktury na~spojení s~koøenem mikrostromu. - Není-li, odpovíme {\sc ne}, stejnì jako kdy¾ není pøítomna pøíslu¹ná spojovací hrana. - Jinak $x$ nahradíme listem makrostromu, do~kterého spojovací hrana vede. Podobnì pro~$y$. -\:Odpovíme podle struktury pro makrostrom. +\:Leží-li $x$ a $y$ v~jednom mikrostromu, zeptáme se struktury pro~mikrostrom. +\:Je-li $x$ uvnitř mikrostromu, zeptáme se mikrostruktury na~spojení s~kořenem mikrostromu. + Není-li, odpovíme {\sc ne}, stejně jako když není přítomna přísluÅ¡ná spojovací hrana. + Jinak $x$ nahradíme listem makrostromu, do~kterého spojovací hrana vede. Podobně pro~$y$. +\:Odpovíme podle struktury pro makrostrom. \endalgo -\s{Analýza:} Operace \ trvá konstantní èas, proto¾e se rozlo¾í na~$\O(1)$ \ù -v~dílèích strukturách a ka¾dý z~nich trvá konstantnì dlouho. V¹ech $n$ operací \ -trvá $\O(n)$, jeliko¾ zpùsobí $\O(n)$ amortizovanì konstantních operací s~mikrostromy, spojovacími -hranami a cestami a $\O(n/\log n)$ operací s~makrostromem, které trvají $\O(\log n)$ amortizovanì -ka¾dá.% -\foot{To je v~prùmìru $\O(1)$ na~operaci a dokonce i amortizovanì, pokud necháme inicializaci -struktury, která je lineární, naspoøit potenciál $\O(n)$, ze~kterého budeme prùbì¾nì platit -sluèování v~makrostromu.} +\s{Analýza:} Operace \ trvá konstantní čas, protože se rozloží na~$\O(1)$ \ů +v~dílčích strukturách a každý z~nich trvá konstantně dlouho. VÅ¡ech $n$ operací \ +trvá $\O(n)$, jelikož způsobí $\O(n)$ amortizovaně konstantních operací s~mikrostromy, spojovacími +hranami a cestami a $\O(n/\log n)$ operací s~makrostromem, které trvají $\O(\log n)$ amortizovaně +každá.% +\foot{To je v~průměru $\O(1)$ na~operaci a dokonce i amortizovaně, pokud necháme inicializaci +struktury, která je lineární, naspořit potenciál $\O(n)$, ze~kterého budeme průběžně platit +slučování v~makrostromu.} -\s{Cvièení:} Zkuste pomocí dekompozice vyøe¹it následující problém: je dán strom, -jeho¾ ka¾dý vrchol mù¾e být oznaèený. Navrhnìte datovou strukturu, která bude umìt -v~èase $\O(\log\log n)$ oznaèit nebo odznaèit vrchol a v~èase $\O(\log n/\log\log n)$ najít -nejbli¾¹ího oznaèeného pøedchùdce. +\s{Cvičení:} Zkuste pomocí dekompozice vyřeÅ¡it následující problém: je dán strom, +jehož každý vrchol může být označený. Navrhněte datovou strukturu, která bude umět +v~čase $\O(\log\log n)$ označit nebo odznačit vrchol a v~čase $\O(\log n/\log\log n)$ najít +nejbližšího označeného předchůdce. \h{Fredericksonova clusterizace} -Mikro/makro-stromová dekompozice není jediný zpùsob, jak stromy rozkládat. Nìkdy -se více hodí následující my¹lenka: +Mikro/makro-stromová dekompozice není jediný způsob, jak stromy rozkládat. Někdy +se více hodí následující myÅ¡lenka: -\s{Definice:} {\I (Fredericksonova clusterizace)} Nech» $k\ge 1$ je pøirozené èíslo -a $T$~strom s~maximálním stupnìm nejvý¹e~3. Pak $k$-clusterizací stromu~$T$ -nazveme libovolný rozklad $V_1\cup\ldots\cup V_t$ mno¾iny~$V(T)$, pro který platí: +\s{Definice:} {\I (Fredericksonova clusterizace)} NechÅ¥ $k\ge 1$ je přirozené číslo +a $T$~strom s~maximálním stupněm nejvýše~3. Pak $k$-clusterizací stromu~$T$ +nazveme libovolný rozklad $V_1\cup\ldots\cup V_t$ množiny~$V(T)$, pro který platí: \itemize\ibull -\:Podgrafy stromu~$T$ indukované jednotlivými~$V_i$ jsou souvislé. -Tìmto podgrafùm budeme øíkat {\I clustery} a znaèit je~$C_i$. -\:Z~ka¾dého clusteru vedou nejvý¹e 3~hrany do sousedních clusterù. -Takovým hranám øíkáme {\I vnìj¹í,} jejich poèet je {\I vnìj¹í stupeò} clusteru $\(C_i)$. -Hrany uvnitø clusterù nazveme {\I vnitøní.} -\:Nech» $\vert C_i\vert$ znaèí poèet vrcholù clusteru~$C_i$. -Pak pro v¹echny clustery platí $\vert C_i\vert \le k$ -a pro clustery vnìj¹ího stupnì~3 dokonce $\vert C_i\vert = 1$. -\:®ádné dva sousední clustery není mo¾né slouèit. +\:Podgrafy stromu~$T$ indukované jednotlivými~$V_i$ jsou souvislé. +Těmto podgrafům budeme říkat {\I clustery} a značit je~$C_i$. +\:Z~každého clusteru vedou nejvýše 3~hrany do sousedních clusterů. +Takovým hranám říkáme {\I vnější,} jejich počet je {\I vnější stupeň} clusteru $\(C_i)$. +Hrany uvnitř clusterů nazveme {\I vnitřní.} +\:NechÅ¥ $\vert C_i\vert$ značí počet vrcholů clusteru~$C_i$. +Pak pro vÅ¡echny clustery platí $\vert C_i\vert \le k$ +a pro clustery vnějšího stupně~3 dokonce $\vert C_i\vert = 1$. +\:Žádné dva sousední clustery není možné sloučit. \endlist -\s{Úmluva:} -Clustery vnìj¹ího stupnì~0 se nazývají {\I izolované,} -stupnì~1 {\I listové,} -stupnì~2 {\I cestové} a -stupnì~3 {\I vìtvicí.} +\s{Úmluva:} +Clustery vnějšího stupně~0 se nazývají {\I izolované,} +stupně~1 {\I listové,} +stupně~2 {\I cestové} a +stupně~3 {\I větvicí.} -\s{Pozorování:} Nech» $C$ a~$D$ jsou sousední clustery (bez újmy na obecnosti $\(C) \ge \(D)$). -Kdy je lze slouèit? Pøedev¹ím $\vert C\vert + \vert D\vert$ musí být nejvý¹e rovno~$k$. Pak mohou -nastat následující pøípady: +\s{Pozorování:} NechÅ¥ $C$ a~$D$ jsou sousední clustery (bez újmy na obecnosti $\(C) \ge \(D)$). +Kdy je lze sloučit? Především $\vert C\vert + \vert D\vert$ musí být nejvýše rovno~$k$. Pak mohou +nastat následující případy: \itemize\ibull -\:Pokud~$C$ i~$D$ jsou listové, lze je slouèit do jednoho izolovaného clusteru. -\:Pokud~$C$ je cestový a $D$~listový, lze je slouèit do listového clusteru. -\:Pokud~$C$ i~$D$ jsou cestové, lze je slouèit do cestového clusteru. -\:Pokud~$C$ je vìtvicí a $D$~listový, lze je slouèit do cestového clusteru. -\:V~ostatních pøípadech sluèovat nelze, nebo» by vznikl cluster vnìj¹ího stupnì~4 - nebo stupnì~3 s~více ne¾ jedním vrcholem. +\:Pokud~$C$ i~$D$ jsou listové, lze je sloučit do jednoho izolovaného clusteru. +\:Pokud~$C$ je cestový a $D$~listový, lze je sloučit do listového clusteru. +\:Pokud~$C$ i~$D$ jsou cestové, lze je sloučit do cestového clusteru. +\:Pokud~$C$ je větvicí a $D$~listový, lze je sloučit do cestového clusteru. +\:V~ostatních případech slučovat nelze, neboÅ¥ by vznikl cluster vnějšího stupně~4 + nebo stupně~3 s~více než jedním vrcholem. \endlist -\s{Vìta:} (Frederickson \cite{frederickson91ambivalent}) Ka¾dá $k$-clusterizace stromu~$T$ -na $n$~vrcholech obsahuje $\O(n/k)$ clusterù. +\s{Věta:} (Frederickson \cite{frederickson91ambivalent}) Každá $k$-clusterizace stromu~$T$ +na $n$~vrcholech obsahuje $\O(n/k)$ clusterů. \proof -Pokud clusterizace obsahuje pouze izolované nebo listové clustery, pak je konstantnì -velká a tvrzení triviálnì platí. - -Pokud navíc obsahuje cestové clustery, musí být clustery propojeny do jedné cesty, -která zaèíná a konèí listovými clustery a ostatní clustery jsou cestové. Cestové -clustery rozdìlíme na velké (alespoò $k/2$ vrcholù) a malé (ostatní). V¹imneme si, -¾e malé spolu nemohou sousedit. Velkých je pøitom nejvý¹e $n/k$, tak¾e malých -nejvý¹e $n/k+1$. - -Zbývá obecný pøípad, v~nìm¾ jsou i vìtvicí clustery. Uva¾me clusterizaèní strom~$S$: -jeho vrcholy odpovídají clusterùm, hrany externím hranám mezi nimi. Tento strom zakoøeòme -v~libovolném vìtvicím clusteru. - -Pokud ve~stromu~$S$ nahradíme ka¾dou nevìtvící se cestu hranou, vznikne nìjaký -komprimovaný strom~$S'$. V~nìm u¾ jsou pouze listové clustery (coby listy) a -vìtvicí clustery (jako vnitøní vrcholy). - -Nyní si v¹imneme, ¾e pro ka¾dý list~$\ell$ stromu~$S$ platí, ¾e tento cluster -spolu s~cestovými clustery nad ním (které se schovaly do hrany mezi~$\ell$ a jeho -otcem) musí mít velikost alespoò~$k$. V~opaèném pøípadì by toti¾ bylo mo¾né -tyto clustery spoleènì s~vìtvicím clusterem nad nimi slouèit do jediného clusteru, -co¾ by poru¹ilo poslední podmínku z~definice clusterizace. - -Proto strom~$S'$ obsahuje nejvý¹e $n/k$ listù. A~jeliko¾ v¹echny jeho vnitøní -vrcholy mají alespoò~2 syny, musí být vnitøních vrcholù také nanejvý¹ $n/k$. - -Zbývá zapoèítat cestové clustery. Uva¾me hranu~$e$ stromu~$S'$ a cestové clustery, -které se do ní zkomprimovaly. U¾ víme, ¾e je-li celková velikost tìchto clusterù~$r$, -mù¾e jich být nanejvý¹ $2r/k + 1$. A~jeliko¾ clustery jsou disjunktní, v~souètu -pøes v¹echny hrany~$e$ dostaneme $2n/k + \hbox{poèet hran stromu~$S'$} = \O(n/k)$. - -Clusterù v¹ech typù je tedy dohromady $\O(n/k)$. +Pokud clusterizace obsahuje pouze izolované nebo listové clustery, pak je konstantně +velká a tvrzení triviálně platí. + +Pokud navíc obsahuje cestové clustery, musí být clustery propojeny do jedné cesty, +která začíná a končí listovými clustery a ostatní clustery jsou cestové. Cestové +clustery rozdělíme na velké (alespoň $k/2$ vrcholů) a malé (ostatní). VÅ¡imneme si, +že malé spolu nemohou sousedit. Velkých je přitom nejvýše $n/k$, takže malých +nejvýše $n/k+1$. + +Zbývá obecný případ, v~němž jsou i větvicí clustery. Uvažme clusterizační strom~$S$: +jeho vrcholy odpovídají clusterům, hrany externím hranám mezi nimi. Tento strom zakořeňme +v~libovolném větvicím clusteru. + +Pokud ve~stromu~$S$ nahradíme každou nevětvící se cestu hranou, vznikne nějaký +komprimovaný strom~$S'$. V~něm už jsou pouze listové clustery (coby listy) a +větvicí clustery (jako vnitřní vrcholy). + +Nyní si vÅ¡imneme, že pro každý list~$\ell$ stromu~$S$ platí, že tento cluster +spolu s~cestovými clustery nad ním (které se schovaly do hrany mezi~$\ell$ a jeho +otcem) musí mít velikost alespoň~$k$. V~opačném případě by totiž bylo možné +tyto clustery společně s~větvicím clusterem nad nimi sloučit do jediného clusteru, +což by poruÅ¡ilo poslední podmínku z~definice clusterizace. + +Proto strom~$S'$ obsahuje nejvýše $n/k$ listů. A~jelikož vÅ¡echny jeho vnitřní +vrcholy mají alespoň~2 syny, musí být vnitřních vrcholů také nanejvýš $n/k$. + +Zbývá započítat cestové clustery. Uvažme hranu~$e$ stromu~$S'$ a cestové clustery, +které se do ní zkomprimovaly. Už víme, že je-li celková velikost těchto clusterů~$r$, +může jich být nanejvýš $2r/k + 1$. A~jelikož clustery jsou disjunktní, v~součtu +přes vÅ¡echny hrany~$e$ dostaneme $2n/k + \hbox{počet hran stromu~$S'$} = \O(n/k)$. + +Clusterů vÅ¡ech typů je tedy dohromady $\O(n/k)$. \qed -\s{Vìta:} (Frederickson \cite{frederickson91ambivalent}) Pro ka¾dé~$k$ lze $k$-clusterizaci -stromu o~$n$~vrcholech najít v~èase $\O(n)$. +\s{Věta:} (Frederickson \cite{frederickson91ambivalent}) Pro každé~$k$ lze $k$-clusterizaci +stromu o~$n$~vrcholech najít v~čase $\O(n)$. \proof -Clusterizaci lze najít upraveným hledáním do hloubky, ale pøi tom je nutné øe¹it -mnoho rùzných pøípadù sluèování clusterù. Místo toho pou¾ijeme následující -hladový algoritmus. - -Nejprve vytvoøíme z~ka¾dého vrcholu triviální cluster. Taková clusterizace -splòuje v¹echny podmínky kromì poslední. Budeme tedy clustery hladovì sluèovat. - -Poøídíme si frontu clusterù, u~nich¾ jsme je¹tì nezkontrolovali sluèitelnost. -Na poèátku do ní umístíme v¹echny clustery. Pak v¾dy odebereme cluster, prozkoumáme -jeho sousedy a pokud mezi nimi je nìjaký, s~ním¾ lze sluèovat, tak to provedeme. -Nový cluster ulo¾íme do fronty, oba staré z~fronty odstraníme. - -V¹imneme si, ¾e pøi ka¾dé kontrole poklesne velikost fronty o~1 -- buïto jsme -nesluèovali a zmizel pouze kontrolovaný cluster, anebo sluèovali, ale pak zmizely -dva clustery a pøibyl jeden. Jeliko¾ kontrolu i slouèení zvládneme v~konstantním -èase, celý algoritmus dobìhne v~èase $\O(n)$. +Clusterizaci lze najít upraveným hledáním do hloubky, ale při tom je nutné řeÅ¡it +mnoho různých případů slučování clusterů. Místo toho použijeme následující +hladový algoritmus. + +Nejprve vytvoříme z~každého vrcholu triviální cluster. Taková clusterizace +splňuje vÅ¡echny podmínky kromě poslední. Budeme tedy clustery hladově slučovat. + +Pořídíme si frontu clusterů, u~nichž jsme jeÅ¡tě nezkontrolovali slučitelnost. +Na počátku do ní umístíme vÅ¡echny clustery. Pak vždy odebereme cluster, prozkoumáme +jeho sousedy a pokud mezi nimi je nějaký, s~nímž lze slučovat, tak to provedeme. +Nový cluster uložíme do fronty, oba staré z~fronty odstraníme. + +VÅ¡imneme si, že při každé kontrole poklesne velikost fronty o~1 -- buďto jsme +neslučovali a zmizel pouze kontrolovaný cluster, anebo slučovali, ale pak zmizely +dva clustery a přibyl jeden. Jelikož kontrolu i sloučení zvládneme v~konstantním +čase, celý algoritmus doběhne v~čase $\O(n)$. \qed -\s{Pou¾ití:} Pøedchozí variantu Union-Find problému bychom také mohli vyøe¹it nahrazením -vrcholù stupnì vìt¹ího ne¾~3 \uv{kruhovými objezdy bez jedné hrany}, -nalezením $(\log n)$-clusterizace, pou¾itím bitové reprezentace mno¾in uvnitø clusterù -a pøebarvovací struktury na~hrany mezi clustery. +\s{Použití:} Předchozí variantu Union-Find problému bychom také mohli vyřeÅ¡it nahrazením +vrcholů stupně většího než~3 \uv{kruhovými objezdy bez jedné hrany}, +nalezením $(\log n)$-clusterizace, použitím bitové reprezentace množin uvnitř clusterů +a přebarvovací struktury na~hrany mezi clustery. -\h{Stromoví pøedchùdci} +\h{Stromoví předchůdci} -\s{Problém:} {\I (Least Common Ancestor alias LCA)} Chceme si pøedzpracovat zakoøenìný strom~$T$ -tak, abychom dokázali pro libovolné dva vrcholy $x,y$ najít co~nejrychleji jejich nejbli¾¹ího -spoleèného pøedchùdce. +\s{Problém:} {\I (Least Common Ancestor alias LCA)} Chceme si předzpracovat zakořeněný strom~$T$ +tak, abychom dokázali pro libovolné dva vrcholy $x,y$ najít co~nejrychleji jejich nejbližšího +společného předchůdce. -\s{Triviální øe¹ení LCA:} +\s{Triviální řeÅ¡ení LCA:} \itemize\ibull -\:Vystoupáme z~$x$ i $y$ do~koøene, oznaèíme vrcholy na~cestách a kde se poprvé - potkají, tam je hledaný pøedchùdce. To je lineární s~hloubkou a nepotøebuje - pøedzpracování. -\:Vylep¹ení: Budeme stoupat z~$x$ a $y$ støídavì. Tak potøebujeme jen lineárnì mnoho - krokù vzhledem ke~vzdálenosti spoleèného pøedchùdce. -\:Pøedpoèítáme v¹echny mo¾nosti: pøedzpracování $\O(n^2)$, dotaz $\O(1)$. -\:\dots\ co dál? +\:Vystoupáme z~$x$ i $y$ do~kořene, označíme vrcholy na~cestách a kde se poprvé + potkají, tam je hledaný předchůdce. To je lineární s~hloubkou a nepotřebuje + předzpracování. +\:VylepÅ¡ení: Budeme stoupat z~$x$ a $y$ střídavě. Tak potřebujeme jen lineárně mnoho + kroků vzhledem ke~vzdálenosti společného předchůdce. +\:Předpočítáme vÅ¡echny možnosti: předzpracování $\O(n^2)$, dotaz $\O(1)$. +\:\dots\ co dál? \endlist -\>Vìrni vtipùm o~matfyzácích a èlánku \cite{bender00lca} pøevedeme radìji tento problém na~jiný. +\>Věrni vtipům o~matfyzácích a článku \cite{bender00lca} převedeme raději tento problém na~jiný. -\s{Problém:} {\I (Range Minimum Query alias RMQ)} Chceme pøedzpracovat posloupnost èísel -$a_1,\ldots a_n$ tak, abychom umìli rychle poèítat $\min_{x\le i\le y} a_i$.% -\foot{V¹imnìte si, ¾e pro sumu místo minima je tento problém velmi snadný.} +\s{Problém:} {\I (Range Minimum Query alias RMQ)} Chceme předzpracovat posloupnost čísel +$a_1,\ldots a_n$ tak, abychom uměli rychle počítat $\min_{x\le i\le y} a_i$.% +\foot{VÅ¡imněte si, že pro sumu místo minima je tento problém velmi snadný.} -\s{Lemma:} LCA lze pøevést na~RMQ s~lineárním èasem na~pøedzpracování a konstantním -èasem na~pøevod dotazu. +\s{Lemma:} LCA lze převést na~RMQ s~lineárním časem na~předzpracování a konstantním +časem na~převod dotazu. -\proof Strom projdeme do~hloubky a poka¾dé, kdy¾ vstoupíme do~vrcholu (a» ji¾ poprvé nebo se do~nìj vrátíme), -zapí¹eme jeho hloubku. ${\rm LCA}(x,y)$ pak bude nejvy¹¹í vrchol mezi libovolnou -náv¹tìvou~$x$ a libovolnou náv¹tìvou~$y$. +\proof Strom projdeme do~hloubky a pokaždé, když vstoupíme do~vrcholu (aÅ¥ již poprvé nebo se do~něj vrátíme), +zapíšeme jeho hloubku. ${\rm LCA}(x,y)$ pak bude nejvyšší vrchol mezi libovolnou +návÅ¡těvou~$x$ a libovolnou návÅ¡těvou~$y$. \qed -\s{Triviální øe¹ení RMQ:} +\s{Triviální řeÅ¡ení RMQ:} \itemize\ibull -\:Pøedpoèítáme v¹echny mo¾né dotazy: pøedzpracování $\O(n^2)$, dotaz $\O(1)$. -\:Pro ka¾dé $i$ a $j\le \log n$ pøedpoèítáme $m_{ij} = \min\{ a_i, a_{i+1}, \ldots, a_{i+2^j-1} \}$, -èili minima v¹ech blokù velkých jako nìjaká mocnina dvojky. Kdy¾ se poté nìkdo zeptá -na~minimum bloku $a_i,a_{i+1},\ldots,a_{j-1}$, najdeme nejvìt¹í~$k$ takové, ¾e $2^k < j-i$ -a vrátíme: +\:Předpočítáme vÅ¡echny možné dotazy: předzpracování $\O(n^2)$, dotaz $\O(1)$. +\:Pro každé $i$ a $j\le \log n$ předpočítáme $m_{ij} = \min\{ a_i, a_{i+1}, \ldots, a_{i+2^j-1} \}$, +čili minima vÅ¡ech bloků velkých jako nějaká mocnina dvojky. Když se poté někdo zeptá +na~minimum bloku $a_i,a_{i+1},\ldots,a_{j-1}$, najdeme největší~$k$ takové, že $2^k < j-i$ +a vrátíme: $$\min( \min\{ a_i, \ldots, a_{i+2^k-1} \}, \min\{ a_{j-2^k}, \ldots, a_{j-1} \} ).$$ -Tak zvládneme dotazy v~èase $\O(1)$ po~pøedzpracování v~èase $\O(n\log n)$. +Tak zvládneme dotazy v~čase $\O(1)$ po~předzpracování v~čase $\O(n\log n)$. \endlist -My si ov¹em v¹imneme, ¾e ná¹ pøevod z~LCA vytváøí dosti speciální instance problému RMQ, -toti¾ takové, v~nich¾ je $\vert a_i - a_{i+1} \vert = 1$. Takovým instancím budeme -øíkat RMQ${\pm}1$ a budeme je umìt øe¹it ¹ikovnou dekompozicí. +My si ovÅ¡em vÅ¡imneme, že náš převod z~LCA vytváří dosti speciální instance problému RMQ, +totiž takové, v~nichž je $\vert a_i - a_{i+1} \vert = 1$. Takovým instancím budeme +říkat RMQ${\pm}1$ a budeme je umět řeÅ¡it Å¡ikovnou dekompozicí. -\s{Dekompozice} pro RMQ${\pm}1$: Vstupní posloupnost rozdìlíme na~bloky velikosti $b=1/2\cdot \log n$, -ka¾dý dotaz umíme rozdìlit na~èást týkající se celých blokù a maximálnì dva dotazy na~èásti blokù. +\s{Dekompozice} pro RMQ${\pm}1$: Vstupní posloupnost rozdělíme na~bloky velikosti $b=1/2\cdot \log n$, +každý dotaz umíme rozdělit na~část týkající se celých bloků a maximálně dva dotazy na~části bloků. -V¹imneme si, ¾e aèkoliv blokù je mnoho, jejich mo¾ných typù (tj. posloupností klesání -a stoupání) je pouze $2^{b-1}\le\sqrt n$ a bloky tého¾ typu se li¹í pouze posunutím -o~konstantu. Vybudujeme proto kvadratickou strukturu pro jednotlivé typy a pro ka¾dý -blok si zapamatujeme, jakého je typu a jaké má posunutí. Celkem strávíme èas -$\O(n + \sqrt n \cdot \log^2 n) = \O(n)$ pøedzpracováním a $\O(1)$ dotazem. +VÅ¡imneme si, že ačkoliv bloků je mnoho, jejich možných typů (tj. posloupností klesání +a stoupání) je pouze $2^{b-1}\le\sqrt n$ a bloky téhož typu se liší pouze posunutím +o~konstantu. Vybudujeme proto kvadratickou strukturu pro jednotlivé typy a pro každý +blok si zapamatujeme, jakého je typu a jaké má posunutí. Celkem strávíme čas +$\O(n + \sqrt n \cdot \log^2 n) = \O(n)$ předzpracováním a $\O(1)$ dotazem. -Mimo to je¹tì vytvoøíme komprimovanou posloupnost, v~ní¾ ka¾dý blok nahradíme -jeho minimem. Tuto posloupnost délky $n/b$ budeme pou¾ívat pro èásti dotazù -týkající se celých blokù a pøipravíme si pro ni \uv{logaritmickou} variantu -triviální struktury. To nás bude stát $\O(n/b\cdot\log (n/b))=\O(n/\log n\cdot\log n)=\O(n)$ na~pøedzpracování +Mimo to jeÅ¡tě vytvoříme komprimovanou posloupnost, v~níž každý blok nahradíme +jeho minimem. Tuto posloupnost délky $n/b$ budeme používat pro části dotazů +týkající se celých bloků a připravíme si pro ni \uv{logaritmickou} variantu +triviální struktury. To nás bude stát $\O(n/b\cdot\log (n/b))=\O(n/\log n\cdot\log n)=\O(n)$ na~předzpracování a $\O(1)$ na~dotaz. -Tak jsme získali algoritmus pro RMQ${\pm}1$ s~konstantním èasem na~dotaz po~lineárním -pøedzpracování a vý¹e zmínìným pøevodem i algoritmus na~LCA se stejnými parametry. -Je¹tì uká¾eme, ¾e pøevod mù¾e fungovat i v~opaèném smìru, a~tak mù¾eme získat -i konstantní/lineární algoritmus pro obecné RMQ. +Tak jsme získali algoritmus pro RMQ${\pm}1$ s~konstantním časem na~dotaz po~lineárním +předzpracování a výše zmíněným převodem i algoritmus na~LCA se stejnými parametry. +JeÅ¡tě ukážeme, že převod může fungovat i v~opačném směru, a~tak můžeme získat +i konstantní/lineární algoritmus pro obecné RMQ. -\s{Definice:} {\I Kartézský strom} pro posloupnost $a_1,\ldots,a_n$ je strom, -jeho¾ koøenem je minimum posloupnosti, tj. nìjaké $a_j=\min_i a_i$, jeho levý podstrom je -kartézský strom pro $a_1,\ldots,a_{j-1}$ a pravý podstrom kartézský strom pro $a_{j+1},\ldots,a_n$. +\s{Definice:} {\I Kartézský strom} pro posloupnost $a_1,\ldots,a_n$ je strom, +jehož kořenem je minimum posloupnosti, tj. nějaké $a_j=\min_i a_i$, jeho levý podstrom je +kartézský strom pro $a_1,\ldots,a_{j-1}$ a pravý podstrom kartézský strom pro $a_{j+1},\ldots,a_n$. -\s{Lemma:} Kartézský strom je mo¾né zkonstruovat v~lineárním èase. +\s{Lemma:} Kartézský strom je možné zkonstruovat v~lineárním čase. -\proof Pou¾ijeme inkrementální algoritmus. V¾dy si budeme pamatovat -kartézský strom pro ji¾ zpracované prvky a pozici posledního zpracovaného -prvku v~tomto stromu. Kdy¾ pøidáváme dal¹í prvek, hledáme místo, kam ho -pøipojit, od~tohoto oznaèeného prvku nahoru. Pov¹imnìme si, ¾e vzhledem -k~potenciálu rovnému hloubce oznaèeného prvku je èasová slo¾itost pøidání -prvku amortizovanì konstantní. +\proof Použijeme inkrementální algoritmus. Vždy si budeme pamatovat +kartézský strom pro již zpracované prvky a pozici posledního zpracovaného +prvku v~tomto stromu. Když přidáváme další prvek, hledáme místo, kam ho +připojit, od~tohoto označeného prvku nahoru. PovÅ¡imněme si, že vzhledem +k~potenciálu rovnému hloubce označeného prvku je časová složitost přidání +prvku amortizovaně konstantní. \qed -\s{Lemma:} RMQ lze pøevést na~LCA s~lineárním èasem na~pøedzpracování a konstantním -èasem na~pøevod dotazu. +\s{Lemma:} RMQ lze převést na~LCA s~lineárním časem na~předzpracování a konstantním +časem na~převod dotazu. -\proof Sestrojíme kartézský strom a RMQ pøevedeme na~LCA v~tomto stromu. +\proof Sestrojíme kartézský strom a RMQ převedeme na~LCA v~tomto stromu. \qed -Výsledky této podkapitoly mù¾eme shrnout do~následující vìty: +Výsledky této podkapitoly můžeme shrnout do~následující věty: -\s{Vìta:} Problémy LCA i RMQ je mo¾né øe¹it v~konstantním èase na~dotaz -po~pøedzpracování v~lineárním èase. +\s{Věta:} Problémy LCA i RMQ je možné řeÅ¡it v~konstantním čase na~dotaz +po~předzpracování v~lineárním čase. -\s{Cvièení:} Vymyslete jednodu¹¹í strukturu pro RMQ, víte-li, ¾e v¹echny dotazy budou na~intervaly stejné délky. +\s{Cvičení:} Vymyslete jednodušší strukturu pro RMQ, víte-li, že vÅ¡echny dotazy budou na~intervaly stejné délky. \references \bye diff --git a/all/ga.tex b/all/ga.tex index 63513ce..c6fe00d 100644 --- a/all/ga.tex +++ b/all/ga.tex @@ -27,13 +27,13 @@ {\nopagenumbers \vglue 1cm -\centerline{\big Martin Mare¹} +\centerline{\big Martin MareÅ¡} \bigskip \bigskip -\centerline{\Big Krajinou grafových algoritmù} +\centerline{\Big Krajinou grafových algoritmů} \bigskip \bigskip -\centerline{\large prùvodce pro støednì pokroèilé} +\centerline{\large průvodce pro středně pokročilé} \vfill \centerline{\epsfxsize=0.7\hsize\epsfbox{krajina.eps}} @@ -41,14 +41,14 @@ \centerline{\large ITI \the\year} \vskip 0.3cm -\centerline{\large Pracovní verze} +\centerline{\large Pracovní verze} \vskip 0.5cm \eject \vglue 0pt plus 1fill -\leftline{\copyright~2007--\the\year~Martin Mare¹} +\leftline{\copyright~2007--\the\year~Martin MareÅ¡} \bigskip -% ISBN má být 2--3cm od spodního okraje stránky +% ISBN má být 2--3cm od spodního okraje stránky %\leftline{\bo ISBN 978-80-239-9049-2} %\vskip 0.5cm \eject @@ -77,42 +77,42 @@ {\obeylines\parskip=0pt\parindent=0pt \vglue 0pt plus 1fill -{\large Mgr. Martin Mare¹, Ph.D.} +{\large Mgr. Martin MareÅ¡, Ph.D.} \medskip -{\Large Krajinou grafových algoritmù} +{\Large Krajinou grafových algoritmů} \bigskip -Vydal Institut Teoretické Informatiky +Vydal Institut Teoretické Informatiky ~~~Univerzita Karlova v Praze -~~~Matematicko-Fyzikální Fakulta -~~~Malostranské nám.~25 +~~~Matematicko-Fyzikální Fakulta +~~~Malostranské nám.~25 ~~~118 00 Praha 1 ~~~jako ZZZ. publikaci v~ITI Series. \bigskip -Sazbu písmem Computer Modern v~programu \TeX\ provedl autor. -Obrázek na titulní stranì nakreslil Jakub Èerný. +Sazbu písmem Computer Modern v~programu \TeX\ provedl autor. +Obrázek na titulní straně nakreslil Jakub Černý. % \medskip -% Vytisklo Reprostøedisko UK MFF. +% Vytisklo Reprostředisko UK MFF. \bigskip -% Vydání první +% Vydání první % 72 stran -% Náklad 100 výtiskù +% Náklad 100 výtisků % Praha 2007 -Vydání jedenapùlté (pracovní verze) +Vydání jedenapůlté (pracovní verze) Praha \the\year \bigskip % {\bo ISBN 978-80-239-9049-2} -% \vskip 0.5cm %% ISBN budi¾ 2--3cm od spodního okraje +% \vskip 0.5cm %% ISBN budiž 2--3cm od spodního okraje } \eject\end diff --git a/errata.tex b/errata.tex index 8037fc7..a23a662 100644 --- a/errata.tex +++ b/errata.tex @@ -6,13 +6,13 @@ \twelvepoint \def\err{ -\>Do kní¾ky se pøes v¹echno sna¾ení autorovo vetøel tiskaøský -¹otek a s~ním i nìkolik chyb. Podívejte se prosím na {\I http:/$\!$/mj.ucw.cz/vyuka/ga/,} -kde se nachází jak online verze kní¾ky, tak seznam známých chyb s~opravami. +\>Do knížky se přes vÅ¡echno snažení autorovo vetřel tiskařský +Å¡otek a s~ním i několik chyb. Podívejte se prosím na {\I http:/$\!$/mj.ucw.cz/vyuka/ga/,} +kde se nachází jak online verze knížky, tak seznam známých chyb s~opravami. \bigskip -\rightline{Pøíjemné ètení pøeje autor\qquad} +\rightline{Příjemné čtení přeje autor\qquad} \bigskip \bigskip diff --git a/sgr.tex b/sgr.tex index af8cdae..bc62a75 100644 --- a/sgr.tex +++ b/sgr.tex @@ -41,8 +41,8 @@ % A kdyz stoji samostatne (aby se naodlamoval) \def\ss#1{\noindent {\bo #1}\par\nobreak} -% Dùkaz -\def\proof{\noindent {\sl Dùkaz:} } +% Důkaz +\def\proof{\noindent {\sl Důkaz:} } % Ctverecek na konci dukazu %\def\qed{{\parfillskip=0pt\quad\hfil\hbox{\I QED} \par}}