Description
给定一棵n个点的带权树,求树上最长的异或和路径
Input
The input contains several test cases. The first line of each test case contains an integer n(1<=n<=100000), The following n-1 lines each contains three integers u(0 <= u < n),v(0 <= v < n),w(0 <= w < 2^31), which means there is an edge between node u and v of length w.
Output
For each test case output the xor-length of the xor-longest path.
Sample Input
4
1 2 3
2 3 4
2 4 6
Sample Output
7
HINT
The xor-longest path is 1->2->3, which has length 7 (=3 ⊕ 4)
注意:结点下标从1开始到N….
Solution
首先我们遇到的一个问题是快速得到任意两点之间路径的异或和的问题。
异或满足交换律和结合律,以0为不变元,这些性质与加法类似,联想加法,我们通常采取sum[u]+sum[v]-sum[lca(u,v)]-sum[lca(u,v)->fa]的方法,再联系异或自身的特殊性质(x^x=0),我们只需要f[u]^f[v]即可
然后我们发现我们需要做的是寻找f[u]^f[v]的最值
这是Trie树的经典问题
Code
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define debug(...) fprintf(stderr, __VA_ARGS__)
template<typename T> inline void read(T &x){
x = 0; T f = 1; char ch = getchar();
while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
while (isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
x *= f;
}
const int INF = 0x7fffffff;
const int N = 1e5+100;
const int LEN = 35;
int bin[LEN], n, f[N];
struct Node{ int v, c; Node *nxt; }pool[N<<1], *tail=pool, *g[N];
struct Trie{ Trie *c[2]; }POOL[N*LEN], *TAIL=POOL, *root;
inline void ckmax(int &x, int y){ if (x < y) x = y; }
inline void addedge(int u, int v, int c){
tail->v = v; tail->c = c; tail->nxt = g[u]; g[u] = tail++;
tail->v = u; tail->c = c; tail->nxt = g[v]; g[v] = tail++;
}
void dfs(int x, int fa){
for (Node *p = g[x]; p; p=p->nxt)
if (p->v != fa) { f[p->v] = f[x] ^ p->c; dfs(p->v, x); }
}
void insert(int x, int p, Trie *&rt){
if (!rt) rt = TAIL++;
if (p<0) return;
insert(x, p-1, rt->c[(x&bin[p])>>p]);
}
int query(int x, int p, Trie *rt){
if (p<0) return 0;
int d = (x&bin[p])>>p;
return rt->c[!d] ? bin[p]+query(x, p-1, rt->c[!d]) : query(x, p-1, rt->c[d]);
}
int main(){
bin[0] = 1; rep(i, 1, 30) bin[i] = bin[i-1] << 1;
read(n);
rep(i, 1, n-1){ int u, v, c;
read(u); read(v); read(c);
addedge(u, v, c);
}
dfs(1, 0);
rep(i, 1, n) insert(f[i], 30, root);
int ans = -INF;
rep(i, 1, n) ckmax(ans, query(f[i], 30, root));
printf("%d\n", ans);
return 0;
}