Description

给定一棵n个点的带权树,求树上最长的异或和路径。

Solution

由异或的性质得到
即根据题目要求,只需要找到一个根节点,然后贪心找跟当前二进制位不同的点即可。
于是先dfs预处理出根节点到每个节点的异或值,同时建立起字典树
然后每次枚举节点 ,在字典树上找最大的匹配结果。

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5; 
vector<pair<int, int> > G[N];
int sum[N];
int tot = 0;
int tree[N * 32][2];
void dfs(int u, int par) {
    for(int i = 0; i < G[u].size(); i++) {
        int v = G[u][i].first;
        if(v == par) continue;
        sum[v] = (sum[u] ^ G[u][i].second); 
        dfs(v, u);
    }
}
void build(int val, int id) {
    for(int i = (1 << 30); i; i >>= 1) {
        bool p = (val & i);
        if(!tree[id][p]) {
            tree[id][p] = ++tot;
        }
        id = tree[id][p];
    }
}
int query(int val, int id) {
    int ans = 0;
    for(int i = (1 << 30); i; i >>= 1) {
        bool p = (val & i);
        if(tree[id][!p]) {
            ans += i;
            id = tree[id][!p];
        } else id = tree[id][p];
    }
    return ans;
}
int main() {
    int n; cin >> n;
    for(int i = 1; i <= n - 1; i++) {
        int u, v, w; cin >> u >> v >> w;
        G[u].push_back({v, w}), G[v].push_back({u, w});
    }
    dfs(1, -1);
    //abort();
    for(int i = 1; i <= n; i++) {
        build(sum[i], 0);
    }
    int ans = 0;
    for(int i = 1; i <= n; i++) {
        ans = max(ans, query(sum[i], 0));
    }
    cout << ans << "\n";
    return 0;
}