原题链接
- 题意:就是给了一棵树,然后求任意两个点之间的距离异或和最大值是多少。
- 题解:很显然的是,随便定义数根,然后就是发现,如果计算 (u) 和 (v) 的边权异或和,那么就是可以是计算出 (u->root) 和 (v->root),因为如果重叠的话,(lca->root oplus lca->root) 显然是 (0) 不影响,所以就是转化了成求出每个点到根部的异或和插入 (01trie),然后再 (O(n)) 遍历找出每个距离根部的异或和在 (trie) 中最大的是多少,然后取 (max) 即可。
- 代码:
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const ll N = 200009;
struct edge {
ll v, w;
};
vector<edge>G[N];
ll d[N];
void dfs(int u, int fa) {
for (auto e:G[u]) {
if (e.v == fa)continue;
d[e.v] = d[u] ^ e.w;
dfs(e.v, u);
}
}
struct Trie {
int tr[N * 24][2], idx;
inline void insert(ll num) {
int p=0;
for (int i = 30; i >= 0; i--) {
ll id = 1&(num >> i);
if (!tr[p][id])tr[p][id] = ++idx;
p = tr[p][id];
}
}
inline ll ask(ll x) {
int p = 0;
ll ret = 0;
for (ll i = 30; i >= 0; i--) {
ll id =1& (x >> i);
if (tr[p][1^id]) {
p = tr[p][1^id];
ret += (1 << i);
} else p = tr[p][id];
}
return ret;
}
}T;
int main() {
ll n;scanf("%lld", &n);
for (int i = 1; i < n; i ++) {
ll u, v, w;
scanf("%lld%lld%lld", &u, &v, &w);
G[u].push_back({v, w});
G[v].push_back({u, w});
}
dfs(1, -1);
T.insert(0);
for (int i = 1; i <= n; i ++) {T.insert(d[i]);}
ll ans = -1;
for (int i = 1; i <= n; i ++) {
ans = max(ans, T.ask(d[i]));
}
printf("%lld
", ans);
}