А2: Бекство
Аутор: Алекса Милисављевић
Текст и тест примери: Алекса Милисављевић
Анализа решења: Јован Бенгин
Тестирање: Андреј Ивашковић
Анализа
Примена K операција се заправо може урадити одједном: избришемо највише K грана, и додамо нове тако да нам граф поново постане стабло. Приметимо да је оптимално да нове гране додајемо на крајеве дијаметара “изрезаних” стабала (стабла на која смо поделили оригинално стабло када смо избрисали неке гране) тако да од њих направимо пут. Тада ће, у оптималном решењу, крајњи дијаметар стабла бити једнак суми дијаметара изрезаних стабала плус број додатих грана.
Случај K=N је еквивалентан са K=N-1, па ћемо разматрати само 0 \leq K < N.
Решење првог и другог подзадатка
Бираћемо гране које бришемо и за сва стабла која нам остану израчунати дијаметре, и те дијаметре ћемо сумирати. Могућих подела у најгорем случају има 2^{N-1} (сваку грану или бришемо или не бришемо), а дијаметар стабла можемо наћи у O(N) - пустимо претрагу из насумичног чвора, обележимо најдаљи чвор од њега као први крај дијаметра, пустимо претрагу из тог чвора и обележимо најдаљи чвор као други крај дијаметра. Овај алгоритам ради јер је најдаљи чвор од произвољног чвора увек крај неког дијаметра, а најдаљи чвор од краја дијаметра је други крај тог дијаметра.
Временска сложеност овог алгоритма је O(2^NTN), што пролази први подзадатак. Међутим, не морамо разматрати свих 2^{N-1} подела - довољне су само оне где бришемо тачно K грана (ако смо избрисали неки број грана, никад не можемо добити лошије решење ако избришемо још неке). Овако ћемо разматрати само {N \choose K} \leq {N \choose N/2} подела, и решење нам лако пролази други подзадатак.
Решење четвртог подзадатка
Пошто је K = 0, решење је само дијаметар почетног стабла. Овде дијаметар не морамо ни тражити O(N) алгоритмом: довољно је да из сваког чвора пустимо по претрагу.
Временска сложеност: O(TN) или O(TN^2)
Решење петог подзадатка
Итерираћемо кроз све гране, и за сваку у O(N) рачунати дијаметре два стабла која добијемо њеним брисањем.
Временска сложеност: O(TN^2)
Решење трећег подзадатка
Није потребно експлицитно тражити дијаметре изрезаних стабала. Лакше нам је да уз свако изрезано стабло само изаберемо неки пут које му припада - у оптималном решењу ће се свакако испоставити да су то дијаметри.
Дефинишимо dp[u][k][x] као највећу могућу суму изабраних путева у подстаблу чвора u ако смо у њему применили k операција, а x је 0, 1, или 2 у зависности од тога колико још можемо да “додајемо” на наш изабран пут. Другим речима, ако је изабран пут тренутног подстабла само чвор u, онда на њега можемо додати путеве који долазе из два различита сина, па је x = 0. Ако се изабран пут тренутног подстабла завршава у u, онда је x=1, а ако је пут већ у потпуности изабран и не додајемо му ништа, онда је x=2.
dp[u][k][x] се налази динамичким програмирањем по стаблу: итерирамо кроз синове, нека је тренутни син v. У dp[u] имамо израчунат dp за подстабло од u, а у dp[u] имамо израчунат dp за стабло сачињено од u и подстабала свих синова кроз које смо до сада итерирали. Желимо да “спојимо” dp вредности за u и v, па да у dp[u] после буде израчунат dp за стабло коме је додато и подстабло од v.
Спајање dp-ова два стабла се може урадити у O(N^2): итерирамо кроз број грана које ћемо брисати у првом стаблу (i), након тога кроз број грана које бришемо у другом (j), и у неки нови dp низ ажурирамо вредности за i + j или i +j +1 избрисаних грана (у зависности од тога да ли бришемо грану од u до v). Постоји неколико случајева: да бришемо грану од u до v и додајемо дужине њихових изабраних путева, да не бришемо грану од u до v већ на пут који се завршава у u додајемо пут који се завршава у v, или да не бришемо грану али да изаберемо само један од два изабрана пута подстабала u и v.
Крајње решење ће бити max(dp[1][K][0], dp[1][K][1], dp[1][K][2]) + K. Ако разматрамо да свако стање у dp[u][k][0] припада и dp[u][k][1], и да свако стање у dp[u][k][1] припада и dp[u][k][2] (што значајно олакшава имплементацију), решење је dp[1][K][2] + K.
Временска сложеност: O(TN^3)
Главно решење
Главно решење је исто као за трећи подзадатак, само што током спајања подстабала не итерирамо кроз вредности које су сигурно немогуће. Другим речима, за сина (v) ћемо само итерирати до величине његовог подстабла, а за корен подстабла (u) ћемо само итерирати до величине тренутног стабла које његов dp представља (јер је немогуће избрисати више грана од тога).
Није тешко доказати да сложеност алгоритма сада постаје O(N^2). Када спајамо dp-ове два стабла, итерирамо до њихових величина - што можемо представити као да се сваки чвор који припада првом стаблу упарује са сваким из другог. Пошто ће након тога сви ти чворови припадати истом стаблу, можемо приметити да ће свака два чвора да се упаре тачно једном - што даје укупно O(N^2) упаривања.
Временска сложеност: O(TN^2)
Бонус: Решите задатак у O(TNlogN).