Kruskalův algoritmus

Kruskalův algoritmus (v České republice se někdy mylně zaměňuje s Borůvkovým algoritmem, ten ale funguje odlišně) je jeden z algoritmů využívaných v teorii grafů k nalezení minimální kostry grafu, jehož hrany mají nezáporné ohodnocení (délku). U souvislého grafu hledá podmnožinu hran, která tvoří strom obsahující všechny uzly, s tím, že celková váha (součet délek) hran grafu je minimální. V případě grafu o více komponentách, algoritmus hledá les minimálních koster, tedy minimální kostru každé komponenty. Kruskalův algoritmus je příkladem hladového algoritmu.

Historie

Algoritmus byl poprvé publikován Josephem B. Kruskalem, zaměstnancem Bellových Laboratoří, v roce 1956. Kruskal v úvodu své práce[1] odkazuje na článek[2] Otakara Borůvky, který pojednává o existenci jediné minimální kostry pro graf s hranami ohodnocenými různými nezápornými čísly.

Kruskal svůj algoritmus popsal následujícím způsobem[1]:

Postup A:

  • Opakuj následující kroky, dokud je to možné:
  • Z hran grafu G {\displaystyle G} , které dosud nebyly vybrány, vyber nejkratší hranu, která nevytváří žádnou kružnici s hranami již vybranými.
  • Množina vybraných hran je kostrou grafu G {\displaystyle G} , která je navíc minimální

V roce 1957 tento algoritmus popsali Loberman a Weinberger, těsně před zveřejněním se autoři o Kruskalově práci dověděli, kvůli detailnějšímu popisu problému a obecnější formulaci však svou práci publikovali.[3]

Ve své práci Kruskal zmiňuje variaci postupu A, ve kterém se opakovaně odebírá nejdelší hrana z grafu, která ještě nezpůsobí rozpad grafu na více podgrafů. Tímto ekvivalentním postupem můžeme také vytvořit minimální kostru grafu.

Postup A':

  • Opakuj následující kroky, dokud je to možné:
  • Z hran G {\displaystyle G} , které dosud nebyly vybrány, vyber nejdelší, která je nerozpojí.
  • Množina nevybraných hran je minimální kostrou grafu G {\displaystyle G} .

Tento alternativní postup byl v roce 1961 nezávisle popsán A. Kotzigem.[4]

Postup B:

Jako obecnější postup pro podmnožinu uzlů grafu formuloval Kruskal postup B:

  • Nechť V je libovolná pevná (neprázdná) podmnožina uzlů grafu G {\displaystyle G} , potom opakuj následující kroky, dokud je to možné:
  • Z hran grafu G {\displaystyle G} , které dosud nebyly vybrány, ale jsou spojeny s uzlem z V {\displaystyle V} nebo s hranou grafu, která již byla vybrána, vyber nejkratší hranu, která nevytváří kružnice s hranami již vybranými.
  • Množina vybraných hran je kostrou grafu G {\displaystyle G} , která je navíc minimální. V případě, že V {\displaystyle V} je množina všech vrcholů grafu G {\displaystyle G} , stává se z obecnějšího postupu B postup A.

Kruskal se ve své práci také zamýšlí nad existencí „duálního“ postupu k B, stejně jako je tomu v případě postupů A a A'. Požadovanou formulaci přináší Rosenstiehl v roce 1967.[5]

První, kdo formuloval postup B byl Vojtěch Jarník v roku 1930[6], obvykle je přisuzován Robertu Primovi, který formuloval obecně kategorii těchto algoritmů[7], z výpočtového hlediska, ale preferoval (stejně jako později Edsger Dijkstra[8]) použití postupu B.

Kruskalův původní důkaz předpokládá různé ohodnocení hran grafu.

Algoritmus

Ekvivalentně můžeme algoritmus popsat tak, že se vždy vybírá taková hrana, která má ze všech možných hran spojujících dva různé podstromy ve vytvářené kostře tu nejmenší váhu.

  • vytvoř les F {\displaystyle F} (množinu stromů), ve kterém je každý uzel grafu samostatným podstromem
  • vytvoř množinu S {\displaystyle S} obsahující všechny hrany grafu
  • dokud je množina S {\displaystyle S} neprázdná
    • z množiny S {\displaystyle S} odeber hranu s minimální váhou
    • pokud tato hrana spojuje dva různé podstromy, přidej ji do lesa F {\displaystyle F} , tak že tyto podstromy sluč do jednoho
    • v jiném případě hranu zahoď

Po skončení běhu algoritmu obsahuje les jedinou komponentu, tvořící minimální kostru grafu.

Složitost

Časová složitost závisí na způsobu implementace řazení a operací s množinovým rozkladem. Pro graf G {\displaystyle G} s počtem uzlů U {\displaystyle U} a hran H {\displaystyle H} je složitost algoritmu O ( U log U ) {\displaystyle O(U\log U)} , což je asymptoticky ekvivalentní s O ( H log U ) {\displaystyle O(H\log U)} . Hrany seřadíme některým z řadících algoritmů podle vah v čase O ( H log H ) {\displaystyle O(H\log H)} , to umožní algoritmu odstranit hranu s minimální vahou v konstantním čase. Pro zaznamenání informací příslušnosti uzlů k jednotlivým komponentám využijeme datovou strukturu disjoint-set (viz Disjoint-set data structure). V této datové struktuře můžeme pro vyhledávání a spojování (sjednocení) využít union-find, které mají složitost O ( U ) {\displaystyle O(U)} . Algoritmus udělá pro každou hranu dvě operace vyhledávání a jednu operaci sjednocení. I jednodušší datové struktury umožňují dosáhnout celkovou složitost O ( H log H ) = O ( H log U ) {\displaystyle O(H\log H)=O(H\log U)} . Pokud jsou hrany již seřazeny, nebo je dokážeme seřadit v lineárním čase, může pomocí sofistikovanějších datových struktur dosáhnout složitost O ( H α ( U ) ) {\displaystyle O(H\alpha (U))} , kde α {\displaystyle \alpha } je inverzní Ackermannova funkce.

Příklad

Původní ohodnocený graf. Čísla poblíž hran označují jejich cenu. Žádná hrana zatím není označena.
AD a CE jsou hrany s nejmenší délkou. Můžeme zvolit libovolnou z dvou hran. Označíme hranu AD.
Nejkratší neoznačenou hranou je CE s délkou 5. Označíme hranu CE.
Nejkratší neoznačenou hranou je DF s délkou 6. Označíme hranu DF.
Následující nejkratší hranou jsou AB a BE s délkou 7. Vybereme hranu AB. Hranu BD označíme červeně, protože mezi B a D již existuje cesta označená zelenou barvou, přidání hrany BD do výběru by způsobilo vznik nežádoucí kružnice ABD.
Proces pokračuje označením následující nejkratší hrany BE. Tři hrany jsou následně označené červeně, protože BC by mohla vytvořit kružnici BCE, DE kružnici DEBA a FE kružnici FEBAD.
Hledání minimální kostry končí přidáním hrany EG. Následující výběr jakékoliv jiné hrany by způsobil vznik kružnice a výsledek by již nebyl kostrou grafu.

Důkaz správnosti

Bez újmy na obecnosti můžeme graf považovat za úplný. Pokud by byl graf neúplný, jednoduše nahradíme hrany, které jsou jeho doplňkem do úplného grafu, za hrany s neporovnatelně větším ohodnocením.

Důkaz se skládá ze dvou částí. První dokazuje, že algoritmus na výstupu skutečně vytvoří kostru. Druhá část důkazu je potvrzením, že kostra je skutečně minimální.

Důkaz vytvoření kostry

Nechť P {\displaystyle P} je souvislý graf s ohodnocenými hranami a Y {\displaystyle Y} je podgrafem P {\displaystyle P} vytvořeným Kruskalovým algoritmem. Y {\displaystyle Y} nemůže obsahovat kružnici, protože poslední hrana přidána do kružnice by spojovala ten samý podstrom a ne dva rozdílné, co je podmínkou pro přidání nové hrany. Y {\displaystyle Y} nemůže být nesouvislý, protože hrany přidané do Y {\displaystyle Y} slučující podstromy byly do Y {\displaystyle Y} přidány, z toho plyne, že Y {\displaystyle Y} je kostrou grafu P {\displaystyle P} .

Důkaz minimální kostry

Provedeme důkaz sporem. Nechť Y {\displaystyle Y} je kostrou, ale ne minimální, zkoumaného grafu a Y 1 {\displaystyle Y_{1}} minimální kostrou grafu, která má nejmenší počet takových hran, které se nenacházejí v Y {\displaystyle Y} . Nechť e {\displaystyle e} je hrana, která by byla jako první přidána algoritmem do Y {\displaystyle Y} , z těch které nejsou v Y 1 {\displaystyle Y_{1}} . Y 1 e {\displaystyle Y_{1}\cup {e}} tvoří kružnici. Jelikož Y {\displaystyle Y} je strom, nemůže obsahovat kružnici. Proto musí zmíněné sjednocení obsahovat hranu f {\displaystyle f} , která v Y {\displaystyle Y} není obsažena. Y 2 = Y 1 e f {\displaystyle Y_{2}=Y_{1}\cup {e}\setminus {f}} je také kostrou grafu a jeho celkové ohodnocení nemůže být menší než ohodnocení Y 1 {\displaystyle Y_{1}} , proto e {\displaystyle e} nemůže mít menší ohodnocení než f {\displaystyle f} . Dalším využitím důkazu sporem dokážeme, že ohodnocení hrany f {\displaystyle f} nemůže být menší než ohodnocení hrany e {\displaystyle e} . Předpokládejme opak ( f {\displaystyle f} má menší ohodnocení jako e {\displaystyle e} ) a pamatujme, že hrany mají být přidány do Y {\displaystyle Y} v pořadí jejich neklesajících ohodnocení. Proto by bylo f {\displaystyle f} testováno pro přidání do podlesu Y 3 Y Y 1 {\displaystyle Y_{3}\subset Y\cap Y_{1}} před e {\displaystyle e} ( e {\displaystyle e} je první hrana Y {\displaystyle Y} , která není v Y 1 {\displaystyle Y_{1}} ). Hrana f {\displaystyle f} ale nevytvoří kružnici v Y 1 {\displaystyle Y_{1}} , proto nemůže vytvořit ani kružnici v Y 3 {\displaystyle Y_{3}} a byla by přidána do vytvářeného stromu. Z předchozích úvah plyne, že ohodnocení e {\displaystyle e} a f {\displaystyle f} jsou stejné a Y 2 {\displaystyle Y_{2}} je minimální kostrou, ale Y 2 {\displaystyle Y_{2}} má o jednu společnou hranu s Y {\displaystyle Y} víc, než má Y 1 {\displaystyle Y_{1}} , co je ve sporu s výběrem Y 1 {\displaystyle Y_{1}} za minimální kostru grafu.

Pseudokód

1 Kruskal(G,w)[9]
2 A := ∅ Vybraná kostra zatím prázdná,
3     for každý uzel u ∈ U //pro každý uzel se vytvoří samostatný podstrom
4         do MAKE-SET(u) 
5   uspořádej H do neklesající posloupnosti podle váhy w
6   for každou hranu [u, v] ∈ H v pořadí neklesajících vah
7     do if FIND-SET(u) != FIND-SET(v) //Hrana [u, v] je vhodná, přidej ji do kostry a spoj odpovídající podstromy
8         then A := A ∪ {[u, v]} 
9             UNION(u, v)
10  return A

Odkazy

Externí odkazy

  • Logo Wikimedia Commons Obrázky, zvuky či videa k tématu Kruskalův algoritmus na Wikimedia Commons
  • Animace Kruskalova algoritmu
  • Bludiště pro Kruskalův a Primů algoritmus
  • Zdrojové kódy (C++) s dokumentací

Literatura

  • GRAHAM, Ronald Lewis; HELL, Pavol. On the History of the Minimum Spanning Tree Problem. Annals of the History of Computing, IEEE. 12. leden-březen 1985, roč. 7, čís. 1, s. 43–57. Dostupné online [PDF]. ISSN 1058-6180. DOI 10.1109/MAHC.1985.10011. (anglicky) 
  • Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. Introduction to Algorithms, Second Edition. MIT Press and McGraw-Hill, 2001. ISBN 0-262-03293-7. Section 23.2: The algorithms of Kruskal and Prim, pp.567–574. (anglicky)
  • KOLÁŘ, Josef. Teoretická informatika. Praha: Česká informatická společnost, 2004. ISBN 80-900853-8-5. Kapitola 5, s. 102. 

Reference

  1. a b KRUSKAL, Joseph Bernard. On the Shortest Spanning Subtree of a Graph and the Traveling Salesman Problem. Proceedings of the American Mathematical Society. Únor 1956, roč. 7, čís. 1, s. 48–50. Dostupné online. DOI 10.2307/2033241. (anglicky) 
  2. BORŮVKA, Otakar. O jistém problému minimálním. In: Práce Mor. Přírodověd. Spol. v Brně. Brno: [s.n.], 1926. Svazek 3. S. 37–58.
  3. LOBERMAN, H; WEINBERGER, A. Formal Procedures for Connecting Terminals with a Minimum Total Wire Length. Journal of the ACM. Únor 1957, roč. 4, čís. 4, s. 428–437. Dostupné online. ISSN 0004-5411. DOI 10.1145/320893.320896. (anglicky) 
  4. KOTZIG, Anton. Súvislé podgrafy s minimálnou hodnotou v konečnom súvislom grafe. Časopis pro pěstování matematiky. 1961, čís. 86. ISSN 0528-2195. 
  5. ROSENSTIEHL, Pierre. L'arbre minimum d'un graphe. In: Theory of Graphs (Int. Symposium, Rome, 1966). New York: Gordon and Breach, 1967. S. 357–368.
  6. JARNÍK, Vojtěch. O jistém problému minimálním. In: Práce Mor. Přírodověd. Spol. v Brně. Brno: [s.n.], 1930. Svazek 6. S. 57–63.
  7. PRIM, Robert Clay. Formal Procedures for Connecting Terminals with a Minimum Total Wire Length. Bell System Technical Journal. 1957, čís. 36, s. 1389–1401. ISSN 1089-7089. (anglicky) 
  8. DIJKSTRA, Edsger Wybe. A note on two problems in connexion with graphs. Numerische Mathematik. Prosinec 1959, roč. 1, čís. 1, s. 269–271. Dostupné online. ISSN 0029-599X. DOI 10.1007/BF01386390. 
  9. KOLÁŘ, Josef. Teoretická informatika. Praha: Česká informatická společnost, 2004. ISBN 80-900853-8-5. Kapitola 5, s. 102. 
Algoritmy hledající minimální kostru grafu
Jarníkův algoritmusBorůvkův algoritmus • Kruskalův algoritmus