AcWing 144 最长异或值路径 (Trie)
题目链接:https://www.acwing.com/problem/content/146/
令 \(D[i]\) 表示 \(i\) 到根路径上的值的异或之和,
则根据异或的性质,\(u,v\) 间路径的异或和即为 \(D[u] ^ D[v]\)
所以问题就变成了在 \(D\) 中选出异或值最大的两个数
Trie树解决即可
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 3000010;
int n, ans;
int D[maxn];
int root = 0, tot = 0;
int h[maxn], cnt = 0;
struct E{
int to, next, w;
}e[100010 << 1];
void add(int u, int v, int w){
e[++cnt].to = v;
e[cnt].w = w;
e[cnt].next = h[u];
h[u] = cnt;
}
struct Trie{
int son[2];
}trie[maxn];
void insert(int x){
int pos = root;
for(int i=31; i>=0; --i){
int num = ((x >> i) & 1);
if(!trie[pos].son[num]) trie[pos].son[num] = ++tot;
pos = trie[pos].son[num];
}
}
int query(int x){
int res = 0;
int pos = root;
for(int i=31; i>=0; --i){
int num = ((x >> i) & 1);
if(trie[pos].son[num ^ 1]){
pos = trie[pos].son[num ^ 1];
res ^= (1 << i);
}else{
pos = trie[pos].son[num];
}
}
return res;
}
void dfs(int u, int par){
for(int i=h[u];i!=-1;i=e[i].next){
int v = e[i].to, w = e[i].w;
if(v == par) continue;
D[v] = D[u] ^ w;
dfs(v, u);
}
}
ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
int main(){
memset(h, -1, sizeof(h)); ans = 0;
n = read();
int u, v, w;
for(int i=1;i<n;++i){
u = read(), v = read(), w = read();
++u, ++v;
add(u, v, w);
add(v, u, w);
}
D[1] = 0;
dfs(1, 0);
insert(D[1]);
for(int i=1;i<=n;++i){
ans = max(ans, query(D[i]));
insert(D[i]);
}
printf("%d\n", ans);
return 0;
}