Jak na to

Můj postup 10/10 (C/C++)

Ze zadání vyplývá, že úloha má co dočinění s kostrou, v tomto případě minimální (Minimum spanning tree).

Myšlenka řešení je následující: Na budování kostry bude využit Kruskalův algoritmus, s podporou union find operací. Dle zadání budeme potřebovat dvě pole, nodes[N], edges[M]. Pole nodes slouží pro union find, pole edges obsahuje seznam hran. Nejdříve je nutné setřídit pole edges dle ceny hrany vzestupně. Pole nodes se inicializuje tak, aby každý prvek měl za svého předka sama sebe. Nyní se bude procházet pole edges a provádět operace union na jednotlivé uzly. Zde je důležité si uvědomit, že kostra může mýt maximálně N - 1 hran, tedy po dosažení tohoto počtu lze iteraci ukončit, union nic nového nespojí.

Pseudokód pro Union Find lze nalézt na wiki https://en.wikipedia.org/wiki/Disjoint-set_data_structure. Je nutné upravit union, tak, aby vyhověl zadání. Jedna z možných modifikací je následující:

V poli nodes by nyní měly být vytvořeny 2 stromy s vrcholy root_x a root_y. Jelikož je pole edges setříděné, stačí operace FIND(x) ukončit po detekci hrany hrana.cena > high. V této fázi by se neměl využívat optimalizovaný find, ale pouze FIND_READ_ONLY(x), tj. který nemodifikuje pole nodes. Jelikož bude potřeba výsledky setřídit dle pravidel výstupu, lze vytvořit pomocné pole, které se posléze zatřídí, ale lepší varianta je použít pole edges a začít přepisovat od začátku se zjištěnými kandidáty, jelikož již není potřeba pole edges udržovat pro potřeby Kruskala.