Submission #442488

#TimeUsernameProblemLanguageResultExecution timeMemory
442488OzyThe Xana coup (BOI21_xanadu)C++17
100 / 100
99 ms21932 KiB
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); i++)
#define repa(i,a,b) for (int i = (a); i >= (b); i--)
#define lli long long int
#define debug(a) cout << #a << " = " << a << endl
#define debugsl(a) cout << #a << " = " << a << ", "

#define MAX 100000

#define apagado 0
#define prendido 1
#define nousado 0
#define usado 1
#define impar 1
#define par 0

#define IMP 200000ll

lli n,a,b;
lli dp[2][2][MAX+2], inicial[MAX+2];
vector<lli> hijos[MAX+2];

lli obtenminimo(vector<int> &nodos, int estado, int paridadusados){
    lli dif = IMP, usados = 0, res = 0;
    for(auto nodo : nodos){
        // SI ES IMPOSIBLE DEJAR EL NODO EN EL ESTADO QUE QUIERES, ENTONCES ES IMPOSIBLE
        if (dp[estado][usado][nodo] >= IMP && dp[estado][nousado][nodo] >= IMP) return IMP;
        if (dp[estado][usado][nodo] < dp[estado][nousado][nodo]){
            ++usados;
            res += dp[estado][usado][nodo];
            if (dp[estado][nousado][nodo] < IMP) dif = min(dif, dp[estado][nousado][nodo] - dp[estado][usado][nodo]);
        }
        else{
            res += dp[estado][nousado][nodo];
            if (dp[estado][usado][nodo] < IMP) dif = min(dif, dp[estado][usado][nodo] - dp[estado][nousado][nodo]);
        }
    }

    usados &= 1; // SACA LA PARIDAD DE LOS USADOS
    if (paridadusados == usados) return res; // EL MINIMO ERA USANDO LOS QUE QUERIAS.
    else if (dif != IMP) return res + dif;   // TENIAS QUE USAR UNO MENOS O MAS, PERO SI HABIA UNA OPCION PARA CAMBIAR
    else return IMP;                         // NO HABIA OPCION PARA CAMBIAR
}

void DFS(lli pos, lli padre) {
    if (pos != 1 && hijos[pos].size() == 1 && inicial[pos] == apagado){
        // SI ES UNA HOJA APAGADA
        dp[apagado][usado][pos] = dp[prendido][nousado][pos] = IMP;
        dp[apagado][nousado][pos] = 0;
        dp[prendido][usado][pos] = 1;
        return;
    }

    if (pos != 1 && hijos[pos].size() == 1 && inicial[pos] == prendido){
        // SI ES UNA HOJA PRENDIDA
        dp[prendido][usado][pos] = dp[apagado][nousado][pos] = IMP;
        dp[prendido][nousado][pos] = 0;
        dp[apagado][usado][pos] = 1;
        return;
    }

    vector<int> nodos;
    for(auto h : hijos[pos]){
        if (h == padre) continue;
        DFS(h, pos);
        nodos.push_back(h);
    }

    // LLENA CADA UNO DE LOS CUATRO CASOS
    dp[apagado][usado][pos] = obtenminimo(nodos, prendido, (inicial[pos] == apagado) ? impar : par) + 1;
    dp[apagado][nousado][pos] = obtenminimo(nodos, apagado, (inicial[pos] == apagado) ? par : impar);
    dp[prendido][usado][pos] = obtenminimo(nodos, prendido, (inicial[pos] == prendido) ? impar : par) + 1;
    dp[prendido][nousado][pos] = obtenminimo(nodos, apagado, (inicial[pos] == prendido) ? par: impar);

}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n;
    rep(i,1,n-1) {
        cin >> a >> b;
        hijos[a].push_back(b);
        hijos[b].push_back(a);
    }
    rep(i,1,n) cin >> inicial[i];

    DFS(1,0);
    a = min(dp[apagado][usado][1], dp[apagado][nousado][1]);

    if (a == IMP) cout << "impossible";
    else cout << a;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...