1.题目链接。题意:给一颗树,带有边权,求一下树上路径异或和最大值。
2.其实和之前BZOJ那道题有着异曲同工之妙,只需要的dfs一下,在dfs的过程中记一下当前节点到根节点的路径上的异或值,然后把这个值插到01字典树上,完事之后每次在字典树上查询最值即可,有人可能会觉得,有的点会重复计算,这样会导致出现的不是一条路径,而是两条或者多条路径交叉,其实这种情况时不存在的,因为只要一个数被计算两次,那么对整体答案将没有贡献,这样这条路径就在这个点断开成两条,所以不会出现交叉。
#include<stdio.h>
#include<string.h>
#include<iostream>
#define MAXN 400010
using namespace std;
struct Trie
{
int tol;
int val[MAXN * 32];
int ch[MAXN * 32][2];
void init()
{ //初始化
tol = 1;
ch[0][0] = ch[0][1] = 0;
}
void insert(int x)
{
int u = 0;
for (int i = 32; i >= 0; i--)
{
int v = (x >> i) & 1;
if (!ch[u][v])
{
ch[tol][0] = ch[tol][1] = 0;
val[tol] = 0;
ch[u][v] = tol++;
}
u = ch[u][v];
}
val[u] = x;
}
int query(int x)
{
int u = 0;
for (int i = 32; i >= 0; i--)
{
int v = (x >> i) & 1;
if (ch[u][v ^ 1]) u = ch[u][v ^ 1];
else u = ch[u][v];
}
return x ^ val[u];
}
}tr;
struct node
{
int val, next, to;
}mp[MAXN*2];
int cnt, head[MAXN];
int ans;
void init()
{
ans = 0;
int cnt = 0;
memset(head, -1, sizeof(head));
}
void add(int u, int v, int w)
{
mp[cnt].to = v;
mp[cnt].val = w;
mp[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int u, int pre, int val)
{
//首先把这个值插入到字典树上去
tr.insert(val);
for (int i = head[u]; ~i; i = mp[i].next)
{
int v = mp[i].to;
if (v == pre)continue;
ans = max(ans, tr.query(val ^ mp[i].val));
dfs(v, u, val ^ mp[i].val);
}
}
int main()
{
int n;
while (~scanf("%d", &n))
{
init();
tr.init();
for (int i = 1; i < n; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
dfs(0, -1, 0);
printf("%d\n", ans);
}
}