Description
In an edge-weighted tree, the xor-length of a path p is defined as the xor sum of the weights of edges on p:
⊕ is the xor operator.
We say a path the xor-longest path if it has the largest xor-length. Given an edge-weighted tree with n nodes, can you find the xor-longest path?
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 0 1 3 1 2 4 1 3 6
Sample Output
7
Hint
The xor-longest path is 0->1->2, which has length 7 (=3 ⊕ 4)
题意: 给出一颗带权树,求一条路径,使路径上边权异或值最大。
分析: 考虑如何快速得到路径上边权的异或值。可以任取一点为根,num数组记录各点到根节点的边权异或值,若想得到两节点x,y之间路径上的异或值,只需要num[x]^num[y],因为两点到根节点经过的重复路径被异或了两遍变成了0,因此异或值就是两点间路径的边权异或值。这样问题就转化为在集合内找到两数使它们的异或值最大,就变成了01字典树的模板题了。
具体代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
//用num数组记录根到每个节点的异或距离,之后放入trie树求两点间最大异或距离
int n, cnt, head[100005], son[3200005][2], idx, num[100005];
struct edges
{
int to, next, w;
}edge[200005];
void init()
{
for(int i = 0; i <= n-1; i++)
head[i] = 0;
cnt = idx = 0;
memset(son, 0, sizeof son);
}
void add(int u, int v, int w)
{
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
void dfs(int now, int fa)
{
for(int i = head[now]; i; i = edge[i].next)
{
int to = edge[i].to, w = edge[i].w;
if(fa == to)
continue;
num[to] = num[now]^w;
dfs(to, now);
}
}
void insert(int x)
{
int now = 0;
for(int i = 30; i >= 0; i--)
{
int t = (x>>i)&1;
if(!son[now][t])
son[now][t] = ++idx;
now = son[now][t];
}
}
int query(int x)
{
int now = 0, temp = 0;
for(int i = 30; i >= 0; i--)
{
int t = (x>>i)&1;
if(!son[now][!t])
{
now = son[now][t];
temp |= (t<<i);
}
else
{
now = son[now][!t];
temp |= ((!t)<<i);
}
}
return temp^x;
}
signed main()
{
while(cin >> n)
{
init();
int u, v, w;
for(int i = 1; i <= n-1; i++)
{
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
dfs(0, -1);
int ans = 0;
for(int i = 0; i <= n-1; i++)
{
insert(num[i]);
ans = max(ans, query(num[i]));
}
printf("%d\n", ans);
}
return 0;
}