Zadanie

Vedúci KSP sa stretli na chate. Ako tomu už ale býva, každý sa spolieha na to, že ostatní donesú na chatu dostatok jedla, aby sa niečo ušlo aj jemu. Vedúci, ktorý si doniesol jedlo, ho má dosť pre každého na chate, no nie je vždy ochotný podeliť sa s ostatnými. Vyšlo to nakoniec ale tak, že v každej dvojici vedúcich je práve jeden z nich ochotný podeliť sa o svoje jedlo s tým druhým vedúcim z tejto dvojice.

Paulínku zaujímalo, koľko najmenej vedúcich muselo doniesť jedlo a ktorí konkrétni vedúci ho museli doniesť na to, aby nikto na chate netrpel hladom. Pomôžete jej zodpovedať túto otázku?

Úloha

Máme \(n\) vedúcich, pričom pre každú dvojicu vedúcich \(i, j\) je vždy práve jeden z nich ochotný podeliť sa s tým druhým o jedlo (ak nejaké doniesol). Každý vedúci, ktorý doniesol jedlo, ho doniesol dostatočne veľa na to, aby sa s ním vedel podeliť s kýmkoľvek, komu je ochotný toto jedlo dať, a aby niečo ostalo aj pre neho samotného. Ak však niekto dostane jedlo od niekoho iného, toto jedlo si ponechá a nedá ho už nikomu ďalšiemu, keďže to nie je jeho vlastné jedlo.

Nájdite čo najmenšiu podmnožinu vedúcich takú, že keď všetci vedúci z tejto podmnožiny donesú jedlo, tak pre každého vedúceho platí, že doniesol jedlo alebo že existuje vedúci, ktorý doniesol jedlo a je ochotný podeliť sa s ním (ide o logické alebo, teda môžu nastať aj oba prípady naraz).

Formát vstupu

V prvom riadku vstupu sú dve medzerou oddelené čísla - číslo \(n\) (\(1 \leq n \leq 1000\)) udávajúce počet vedúcich, ktorí prišli na chatu, a číslo \(s\) označujúce číslo aktuálnej sady vstupov (\(s = 0\) v prípade, že sa jedná o sample, inak \(s \in {1, 2, 3, 4}\) podľa čísla aktuálnej sady).

V každom z nasledujúcich \(n\) riadkov je \(n\) čísel, z ktorých každé je buď 0, alebo 1. Označme \(j\)-te číslo v \(i\)-tom z týchto riadkov ako \(A_{ij}\). Ak \(A_{ij} = 1\), znamená to, že vedúci \(i\) je ochotný podeliť sa s vedúcim \(j\) o svoje jedlo, inak vedúci \(i\) nie je ochotný podeliť sa s vedúcim \(j\) o svoje jedlo. Špeciálne pre každé \(i\) je \(A_{ii}\) tiež rovné nule, keďže nedáva zmysel, aby sa vedúci sám so sebou delil o jedlo.

Zároveň pre každú dvojicu rôznych vedúcich \(i, j\) platí, že buď vedúci \(i\) je ochotný podeliť sa s vedúcim \(j\) o svoje jedlo, alebo vedúci \(j\) je ochotný podeliť sa s vedúcim \(i\) o svoje jedlo (teda nastáva práve jeden z týchto prípadov).

Formát výstupu

Vypíš dva riadky. V prvom z nich vypíš jedno celé číslo \(k\), a to čo najmenší počet vedúcich, ktorí museli na chatu doniesť jedlo, aby sa každý vedúci mohol najesť. Tento počet nemusí byť nutne najnižší možný, ale stačí, že nebude vyšší než nejaký limit \(k_{\max}\), ktorý je pre každú sadu rozdielny a v každej ďalšej sade sa postupne znižuje, viď. časť Hodnotenie. V druhom riadku následne v ľubovoľnom poradí vypíš čísla \(k\) vedúcich, ktorí museli doniesť na chatu jedlo. Vedúcich číslujeme od \(1\) do \(n\).

Hodnotenie

Sú 4 sady vstupov, v každej platí \(1 \leq n \leq 1000\). Body za jednotlivé sady sú následne udeľované podľa maximálnej hodnoty \(k\), ktorú Tvoj program bude potrebovať spomedzi vstupov pre danú sadu. V jednotlivých sadách tak pre získanie bodov za danú sadu platia nasledujúce obmedzenia:

Sada 1 2 3 4
\(k_{\max} \leq\) \(500\) \(100\) \(20\) \(9\)

Ak Tvoj program prekročí časový limit v ľubovoľnom vstupe alebo vypíše skupinu vedúcich, ktorá nezaručí to, že každý vedúci bude mať prístup k jedlu, tak Tvoj program skončí chybovou hláškou (TLE v prvom prípade a WA v druhom prípade) a nedostaneš žiadne body za danú sadu. Podobne ak v nejakom vstupe prekročíš hodnotu \(k_{\max}\) danej sady, Tvoj program skončí chybou WA a nedostaneš za danú sadu žiadne body.

V popise k tejto úlohe okrem popísania postupu, ktorým Tvoj program vyberá vhodné podmnožiny vedúcich, nezabudni tiež napísať hodnotu \(k\), ktorú tento postup v najhoršom prípade dosahuje, spolu s dôkazom tejto hornej hranice veľkosti vybratej podmnožiny. Okrem toho tiež popíš a zdôvodni časovú a pamäťovú zložitosť svojho algoritmu, hoci sa pri hodnotení na ne nebude klásť až taká váha, ako na veľkosť horného odhadu hodnoty \(k\) a na dôkaz toho, že ju popísaný postup nikdy neprekročí.

Príklady

Input:

3 0
0 1 1
0 0 0
0 1 0

Output:

1
1

Vedúci \(1\) je ochotný podeliť sa o jedlo s obomi zvyšnými vedúcimi, preto stačí, aby doniesol jedlo iba on.

Input:

4 0
0 1 0 0
0 0 1 0
1 0 0 1
1 1 0 0

Output:

2
2 4

Vedúci \(1, 2, 3, 4, 1\) v tomto poradí tvoria cyklus toho, kto je komu ochotný dať jedlo, preto stačí vybrať napríklad každého druhého vedúceho v tomto cykle. Ak by doniesol len jeden vedúci jedlo, nestačilo by to na nasýtenie každého.

Prvé nápady

Situáciu z tejto úlohy si vieme predstaviť pomocou orientovaného grafu, kde vrcholy zodpovedajú vedúcim a od vedúceho \(i\) k vedúcemu \(j\) vedie hrana práve vtedy, keď vedúci \(i\) je ochotný podeliť sa s vedúcim \(j\). Chceme vybrať takú množinu vrcholov, aby bol každý vrchol v tejto množine alebo aby susedil s nejakým vrcholom z tejto množiny.

Najľahšie riešenie samozrejme dosiahneme tak, že každý vedúci donesie jedlo. Takto však bude musieť doniesť jedlo až všetkých \(n \leq 1000\) vedúcich, čo je veľmi neoptimálne.

O niečo lepšie riešenie vieme dosiahnuť tak, že zaručíme, aby každý vedúci, ktorý donesie jedlo, pokryl ešte aspoň nejakého jedného ďalšieho vedúceho, ktorý tak nebude musieť doniesť jedlo. To vieme spraviť tak, že popárujeme vedúcich do dvojíc \((1,2)\), \((3, 4)\) a tak ďalej, pričom v prípade nepárneho počtu vedúcich nám ostane na konci ešte jeden nespárovaný vedúci.

Vieme, že v každej dvojici je práve jeden vedúci ochotný podeliť sa s tým druhým, takže v každej dvojici sa nám stačí pozrieť na to, ktorý vedúci z danej dvojice to je. Potom stačí, aby tento vedúci doniesol jedlo, a pokryje tým aj druhého vedúceho z danej dvojice. Pre nepárne \(n\) posledného nespárovaného vedúceho vieme vyriešiť zrejme tak, že aj on samotný ešte prinesie jedlo.

Týmto postupom vieme vybrať \(\lceil n/2 \rceil\) vedúcich tak, že pokryjeme každého vedúceho, čo nám stačí na zisk \(2\) bodov. Časová aj pamäťová zložitosť tohto postupu je \(O(n^2)\) kvôli načítavaniu vstupu, zvyšok už prebehne v čase lineárnom od \(n\), keďže počet dvojíc je lineárny od \(n\) a v každej sa nám stačí pozrieť len na to, z ktorého vrcholu do ktorého vedie hrana.

Optimálne riešenie

Keď sa pokúsime vyššie uvedené riešenie vylepšiť a zaručiť tak napríklad pokrytie viacerých než dvoch vedúcich jedným vedúcim, zistíme, že to už takto ľahko zlepšiť nejde. Napríklad spomedzi trojice vedúcich už nemusíme vedieť vybrať jedného vedúceho, ktorým pokryjeme zvyšných dvoch.

Môže nám ale napadnúť pažravé (greedy) riešenie, v ktorom vždy vyberieme nejakého nepokrytého vedúceho, ktorý nám pokryje čo najviac ešte nepokrytých vedúcich. Takto vyberáme ďalších vedúcich s jedlom až dokým nepokryjeme úplne všetkých vedúcich. Toto riešenie znie prirodzene, no bez ďalšieho dôkazu nie je vôbec jasné, ako dobré v skutočnosti je.

Poďme sa bližšie pozrieť na jeden krok tohto postupu. Nech je ešte nepokrytých \(x\) vedúcich a my z nich vyberáme toho vedúceho, ktorý pokryje čo najviac nepokrytých vedúcich. Poďme spočítať, koľko vedúcich takto pokryjeme.

Tu nám pomôže grafová interpretácia tejto úlohy. Ľubovoľný nepokrytý vrchol totiž určite pokryje sám seba a okrem toho pokryje práve toľko vrcholov, koľko hrán z neho vedie k ešte nepokrytým vrcholom.

V podgrafe celého grafu tvorenom len nepokrytými vrcholmi a hranami medzi nimi pritom máme hranu medzi každou dvojicou rôznym vrcholom, a to orientovanú práve jedným smerom, takže hrán v tomto podgrafe je \(\binom{x}{2} = \frac12 x (x-1)\). Každá táto hrana vychádza z nejakého z \(x\) ešte nepokrytých vrcholov, takže z jedného vrcholu vychádza priemerne \(\frac12 (x-1)\) hrán.

Keď potom vyberieme nepokrytý vrchol, z ktorého vychádza najviac hrán do nepokrytých vrcholov, tak z neho bude určite vychádzať aspoň priemerný počet hrán, teda aspoň \(\frac12 (x-1)\). V opačnom prípade by totiž z každého nepokrytého vrcholu vychádzalo menej než \(\frac12 (x-1)\) hrán do nepokrytých vrcholov, a tak celkovo zo všetkých \(x\) nepokrytých vrcholov by dokopy vychádzalo menej než \(\frac12 x(x-1)\) hrán do ďalších nepokrytých vrcholov, teda hrán medzi nepokrytými vrcholmi by bolo menej než \(\frac12 x(x-1)\), čo je ale spor s tým, že hrán medzi danými vrcholmi je práve \(\frac12 x(x-1)\).

Vybraný vrchol tak pokryje sám seba a okrem toho ešte aspoň \(\frac12 (x-1)\) ďalších nepokrytých vrcholov, teda v jednom kroku pokryjeme aspoň \(1 + \frac12 (x-1) = \frac12 (x+1)\) ešte nepokrytých vrcholov. Všimnime si, že v jednom kroku pokryjeme vždy viac než polovicu všetkých ešte nepokrytých vrcholov, takže počet potrebných krokov ako aj počet vybraných vrcholov bude približne logaritmický oproti celkovému počtu vrcholov.

Poďme presne určiť potrebnú veľkosť vybranej podmnožiny vedúcich pre \(n \leq 1000\). Zrejme nám stačí určovať tento počet pre maximálny počet vedúcich, teda pre \(n=1000\). Po vybraní \(0\) vedúcich tak máme \(x=1000\) nepokrytých vedúcich a v každom ďalšom kroku nám počet nepokrytých vedúcich klesne z \(x\) aspoň na \(x - \frac12 (x+1) = \frac12 (x-1)\), pričom tento počet musí ostať celočíselný, takže v skutočnosti najväčší možný počet nepokrytých vedúcich po ďalšom kroku je \(\lfloor \frac12 (x-1) \rfloor\). Maximálne počty nepokrytých vedúcich po \(k\) vybraných vedúcich týmto postupom tak vieme postupne odsimulovať a zapísať do nasledovnej tabuľky:

\(k\) \(0\) \(1\) \(2\) \(3\) \(4\) \(5\) \(6\) \(7\) \(8\) \(9\)
\(x_{\max}\) \(1000\) \(499\) \(249\) \(124\) \(61\) \(30\) \(14\) \(6\) \(2\) \(0\)

Vidíme, že pre \(n \leq 1000\) skutočne stačí vybrať \(9\) vedúcich na pokrytie všetkých vedúcich, čo už stačí na zisk plného počtu bodov.

Zamyslime sa ešte nad tým, akú časovú a pamäťovú zložitosť má tento postup. Pri najjednoduchšom spôsobe implementácie prechádzame v každom kroku cez \(n\) vrcholov a pre každý nepokrytý vrchol zrátame, do koľkých ďalších nepokrytých vrcholov z neho vedú hrany, prechodom cez všetkých \(n\) možností na jeho suseda. Následne vrchol s maximálnym počtom susedov a aj všetkých jeho susedov označíme za pokrytých a pokračujeme ďalej. Takýchto krokov je \(O(\log n)\), takže takto dostávame celkovo časovú zložitosť \(O(n^2 \log n)\).

Toto vieme ešte mierne vylepšiť tak, že si v hešovacej tabuľke udržiavame všetky ešte nepokryté vrcholy a v každom kroku prechádzame len cez ne. Takto krok, v ktorom je nepokrytých vrcholov \(x\), zaberie čas \(O(x^2)\). Keďže zároveň v každom kroku klesne veľkosť nepokrytej množiny aspoň na polovicu, tak tento postup uskutoční rádovo \(n^2 + (n/2)^2 + (n/4)^2 + \dots + (n/n)^2\) operácií. Túto hodnotu vieme zhora ohraničiť \(n^2\) násobkom súčtom nekonečného geometrického radu s počiatočnou hodnotou \(1\) a kvocientom \(1/4\), teda hodnotou \(n^2 \cdot \frac{1}{1-\frac14} = \frac43 n^2\), takže časová zložitosť je teraz dokonca \(O(n^2)\).

Po hlbšom zamyslení vieme dokonca zistiť, že aj časová zložitosť pôvodného algoritmu bez hešovacej tabuľky je v skutočnosti \(O(n^2)\). V každom kroku totiž lineárne prechádzame všetkými vrcholmi, ale ďalej počítame počty hrán len pre tie nepokryté vrcholy. Keďže je krokov \(O(\log n)\), tak lineárne prechody všetkými vrcholmi vyjdú dokopy len na čas \(O(n \log n)\) a prechody všetkými hranami, kde za prvý vrchol vezmeme vždy len nejaký nepokrytý vrchol, zaberie čas rádovo \(n\cdot n + n/2 \cdot n + n/4 \cdot n + \dots + n/n \cdot n\), čo je opäť zhora ohraničené súčtom nejakého nekonečného geometrického radu, ktorého hodnota je tentokrát \(2n^2\), takže aj časová zložitosť pôvodného algoritmu je \(O(n^2)\)

Pamäťová zložitosť je \(O(n^2)\), keďže si musíme pamätať informácie o všetkých hranách.

Diskusia

Tu môžte voľne diskutovať o riešení, deliť sa o svoje kusy kódu a podobne.

Pre pridávanie komentárov sa musíš prihlásiť.