Submission #1323888

#TimeUsernameProblemLanguageResultExecution timeMemory
1323888jmuzhenThe Xana coup (BOI21_xanadu)C++20
100 / 100
51 ms17712 KiB
#include <bits/stdc++.h>
using namespace std;

/*
so we did get that every child's edges are basically forced, and so every edge is forced
but intsead of calculating this edge and having only (i, child) in state
we make another dimension: (i, current, child)
or rather in the imple: (u, parent, current)
so we don't need to do the case work...
*/

#define int long long

constexpr int INF = 1e9+10;

vector<int> parent, order;
vector<vector<int>> adj;
int n;
int root = 1;

void dfs_parent(int u, int p = -1) {
    for (int v : adj[u]) {
        if (v == p) continue;
        parent[v] = u;
        dfs_parent(v, u);
    }
    order.push_back(u);
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >>n;
    adj.resize(n + 1);
    for (int i = 0; i < n - 1; i++) {
        int a, b; cin >> a >> b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    vector<int> A(n + 1);
    for (int i = 1; i <= n; i++) cin >> A[i];

    parent.resize(n + 1, -1);
    dfs_parent(root);

    // minimum in the subtree if the parent(u) pressed a and u pressed b
    vector<array<array<int, 2>, 2>> dp(n+ 1);
    for (int i = 1; i <= n; i++)
        for (int a = 0; a < 2; a++)
            for (int b = 0; b < 2; b++)
                dp[i][a][b] = INF;

    for (int u : order) {
        for (int P = 0; P <= 1; P++) { // the one that parent(u) pressed
            for (int X = 0; X <= 1; X++) { // the one that u pressed 
                int best[2] = {0, INF};

                for (int v : adj[u]) { 
                    if (v == parent[u]) continue;

                    int c0 = dp[v][X][0];
                    int c1= dp[v][X][1];

                    int next0 = min(best[0] + c0, best[1] + c1);
                    int next1 = min(best[0] + c1, best[1] + c0);
                    best[0] = next0;
                    best[1] = next1;
                }

                // if A[u] == 1, then X ^ P must be 1
                // if A[u] == 0, then X ^ P must be 0
                // so required: A[u] ^ X ^ P
                int need = (A[u] ^ X ^ P); 
                int childrenCost = best[need];
                if (childrenCost >= INF) {
                    dp[u][P][X] = INF;
                } else {
                    dp[u][P][X] = childrenCost + X;
                }
            }
        }
    }

    int ans = min(dp[root][0][0], dp[root][0][1]);
    if (ans >= INF) cout << "impossible\n";
    else cout << ans << "\n";
}
#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...