洛谷 P4551 最长异或路径

题意

给定一棵树 , 求树上任意两个节点之间异或可能值的最大值

思路

任意两个节点之间的异或路径都可以转换为该节点到树根路径再异或上另一个节点到树根的异或路径

对树进行\(dfs\) , 求出所有节点到树根的路径异或值

然后就是要在这若干个数字中找到两个值使得异或值最大

此时构建 \(trie\)树 , 然后求即可

需要注意的是 , 假设每个数字二进制都不一样 ,最大为\(10^7 \lt 2^{25}\) , 那么\(trie\)树居然要开25倍空间QAQ

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long int
inline int read() {
    int ans = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')f = -1;
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0') {
        ans = ans * 10 + ch - '0';
        ch = getchar();
    }
    return ans * f;
}
const int N = 1e5+10;
struct Edge {
    int v,w;
};
vector<Edge> ed[N];
int val[N];
int a,b,c;
int ch[N<<4][2];
int idx;
void insert(int x) {
    bitset<32>v(x);
    int p=0;
    for (int i = 31; i>=0; i--) {
        int c = v[i];
        if (!ch[p][c]) {
            ch[p][c] = ++idx;
        }
        p = ch[p][c];
    }
}

void dfs(int u,int fa) {
    for (auto e : ed[u]) {
        if (e.v == fa)
            continue;
        val[e.v] = val[u] ^ e.w;
        dfs(e.v,u);
        val[e.v] = val[u] ^ e.w;
    }
    insert(val[u]);
}
int query(int x) {
    int res = 0;
    int p = 0;
    bitset<32>v(x);
    for (int i = 31; i>=0; i--) {
        int c=  v[i];
        if (ch[p][!c]) {
            res = res<<1|1;
            p = ch[p][!c];
        }
        else {
            res = res << 1;
            p = ch[p][c];
        }
    }
    return res;
}
signed main() {
    int n =read();
    for (int i =1; i<= n-1; i++) {
        a =read(), b=read(),c=read();
        ed[a].push_back({b,c});
        ed[b].push_back({a,c});
    }
    dfs(1,-1);
    int ans = 0;
    for (int i = 1; i<= n; i++) {
        ans = max(ans,query(val[i]));
    }
    cout<<ans<<"\n";
    return 0;
}
posted @ 2025-04-13 18:54  Guaninf  阅读(14)  评论(0)    收藏  举报