Боје
Аутор: Алекса Плавшић
Текст и тест примери: Димитрије Ердељан
Анализа решења: Слободан Митровић
Тестер: Владимир Миленковић
Анализа
Лако је видети да се овај задатак може свести на тражење броја повезаних компоненти међу пољима која нису обојена. Сваку такву компоненту можемо обојити новом обојом. У остатку решења ћемо описати како се број повезаних компоненти може ефикасно наћи под ограничењима датим у овом задатку.
Решење у O(N \cdot M)
Да бисмо пронашли број компоненти, једноставно можемо да применимо Depth First Search (DFS) алгоритам од сваког необојеног поља које нисмо до сада овим алгоритмом посетили. Пошто број чворова и грана у графу који представљају необојена поља има сложеност O(N \cdot M), овај приступ би био врло спор за највеће тест примере.
Посматрајмо пример где је N = M = 10^9 и K = 10^5. У том примеру постоје “велики” делови табле који су необојени а повезани. Интуитивно, уместо да свако поље тих “великих” делова посматрамо као чвор, било би згодно ако бисмо цео “велики” део посматрали као један чвор. У том случају би горе описани DFS-приступ имао далеко мању сложеност. Наравно, главно питање овде је како изабрати велике делове тако да је згодно са њима радити, а успут свести број чворова које посматрамо на мали број. У остатку решења ћемо се фокусирати на ово питање.
“Велики” делови табле и решење у O(К \cdot \log{K})
Сада ћемо објаснити како да од улаза направимо граф који има O(K) чворова и O(K) грана.
Чворови
Најпре, узастопне колоне који немају иједно црно поље ћемо посматрати као један чвор. Пошто је, сем првог и последњег, сваки такав чвор ограничен колонама које имају бар једно црно поље, број таквих чворова је највише K + 1.
Посматрајмо сада колону која има бар једно црно поље. Ако колона има t црних поља тада се она може изделити у t + 1 или мање низова узасотпних необојених поља. Сваки од тих низова ћемо посматрати као посебан чвор. Таквих чворова има највише 2 K.
Гране
Да бисмо излистали гране, посматраћемо по две суседне колоне и чворове које оне дефинишу, под условом да бар једна од колона има бар једно црно поље. (Две суседне колоне које немају црна поља су део истог чвора.) Нека је C_1 листа чворова прве, а нека је C_2 листа чворова друге колоне. Сваки чвор v је представљен као пар (a, b), што значи да је v подниз узастопних необојених поља који се у одговарајућој колони пружају између редова a и b. Претпоставимо да су чворови у C_1 и C_2 сортирани у растућем поретку по првој координати. Тада, се следећи алгоритам може применити да се нађу све гране између чворова у C_1 и C_2.
Нека је v_1 = (a_1, b_1) \in C_1 тренутни чвор који обрађујемо у C_1, а v_2 = (a_2, b_2) \in C_2 тренутни чвор који обрађујемо у C_2. На почетку, v_1 је први чвор из C_1, а v_2 је први чвор из C_2. Примењујемо следеће све док нисмо прошли све чворове из бар C_1 или C_2:
- Ако b_1 < a_2, поставимо v_1 да буде следећи чвор у C_1.
- Ако b_2 < a_1, поставимо v_2 да буде следећи чвор у C_2.
- Иначе, додамо грану између v_1 и v_2. Ако је b_1 < b_2, онда поставимо v_1 да буде следећи чвор у C_1, а иначе поставимо v_2 да буде следећи чвор у C_2.
Није тешко проверити да се на овај начин заиста дефинишу све гране између чворова у C_1 и C_2. Поред тога, сваки пут кад се дода грана чвор v_1 или чвор v_2 се помере за један место. То значи да се у овом процесу дода највише |C_1| + |C_2| грана. Пошто је свака колона суседна са највише две друге колоне и пошто смо рекли да је укупан број чворова K + 1 + 2 K, овим процесом се дода највише 2 (3K + 1) грана.
Да бисмо пронашли број повезаних компоненти над оваквим графом можемо да применимо DFS; алтернативно, уместо DFS-а можемо искористити union-find структуру. Cортирање чворова у колони C се може урадити у времену O(|C| \log{|C|}), тако да је укупна сложеност целог алгоритма O(K \log{K}).
Алтернативно решење
Овај задатак са такође може решити применом Ојлерове формуле за планарне графове. Наиме, ако нам је дат планаран граф G на n чворова, са m грана, f повезаних области и c компоненти, тада важи n - m + f = 1 + c. Ову формулу можемо искористити да решимо задатак на следећи начин.
За четири поља која имају координате (x, y), (x, y + 1), (x + 1, y), (x + 1, y + 1) кажемо да чине 2x2 квадрат.
Замислићемо да је табла оивичена траком црне боје. Целу ту траку ћемо посматрати као један чвор. Потом, у центар сваког црног поља ћемо ставити чвор. Повезаћемо два чвора граном ако одговарајућа црна поља деле макар једно теме, и поред тога избацићемо гране које спајају наспрамна поља у 2x2 црном квадрату (грану која спаја поља (x, y) и (x + 1, y + 1), и грану која спаја поља (x + 1, y), (x, y + 1)). Ове гране избацујемо да бисмо очували планарност. Приметимо да је ова дефиниција суседних црних поља другачија него она у поставци задатка. Такође ћемо повезати траку која оивичава таблу са сваким чвором који додирује ивицу табле, тј., са сваким чвором који се налази у првом или у последњем реду или у првој или у последњој колони. Овај граф је планаран. Поред тога, граф има O(K) грана, тако да вредност c можемо лако наћи, на пример, DFS алгоритмом.
Користећи наведену формулу можемо да израчунамо f. Али шта представља f? Најпре, свака четири чвора која чине 2x2 квадрат ће у овој дефиницији планарног графа формирати једну повезану област. Такође ће и свака три чвора у “Г облику” (тј. имају координате (x, y), (x, y + 1), (x + 1, y)) и ротацијама ове конфигурације чинити повезане области. Поред ових области, f броји повезане области које одговарају необојеним пољима, што је управо број оних области које су решење овог проблема. Дакле, да бисмо решили овај проблем, потребно је да од f одузмемо 2x2 црне квадрате.
За имплементирање DFS-а можемо сместити сва црна поља у hash мапу, или на пример у структуру map у C++. Приступом овој мапи је онда лако наћи које суседе има дати чвор.
Да резимирамо, да бисмо решили проблем, потребно је да: (1) направимо граф као што је то описано; (2) израчунамо c; (3) пребројимо 2x2 црне квадрате, и пребројимо црне квадрате који чине “Г облик” и његове ротације; и (4) користећи наведену формулу израчунамо решење овог проблема.