1. 程式人生 > >(構造/樹形dp)牛客訓練賽32-B:Xor Path

(構造/樹形dp)牛客訓練賽32-B:Xor Path

https://ac.nowcoder.com/acm/contest/272/B
計算樹上每個點到其他點得最短路經過的點的異或值的異或值。
第一行一個整數n。
接下來n-1行,每行2個整數u,v,表示u,v之間有一條邊。
第n+1行有n個整數,表示每個點的權值ai。
輸出所有path(i, j)的異或值

剛開始看到題意求最短路的異或值,以為是lca求樹上路徑,然後發現後面要是對每個點去求其他點的路徑再異或,光這個就n^2了。
正解是對每個點去求被多少條邊經過,因為異或的關係,偶數次經過就不算該點了

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 5;

vector<int> E[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, u, v;
    cin >> n;
    vector<int> val(n + 1), sz(n + 1), num(n + 1);
    for(int i = 1; i < n; i++) {
        cin >> u >> v;
        E[u].emplace_back(v);
        E[v].emplace_back(u);
    }
    for(int i = 1; i <= n; i++) cin >> val[i];
    function<void(int, int)> dfs = [&](int u, int pre) {
        //cout << "u = " << u << " ,pre = " << pre << '\n';
        sz[u] = 1;
        for(int v : E[u]) {
            if(v != pre) {
                dfs(v, u);
                num[u] = num[u] + sz[u] * sz[v] & 1;
                sz[u] += sz[v];
            }
        }
        num[u] = num[u] + (sz[u]) * (n - sz[u]) & 1;
    };
    dfs(1, 0);
    int ans = 0;
    for(int i = 1; i <= n; i++)
        if(num[i] & 1) ans ^= val[i];
    cout << ans << endl;
}