The xor-longest Path
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:
{xor}length(p)=\oplus{e \in p}w(e)
⊕ 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
题意,给出一棵树,每条边有边权,选择两个点x,y,把从x到y的路径上所有边权异或起来,求结果最大多少。
分析:设f[i]为从根节点到i的路径上所有边权异或起来的结果,显然x到y的结果就是f[x]^f[y],那么只需求所有f[x]^f[y]中的最大值。我们可以把每个f[i]看作长度为32的二进制数,不够的前面补0,将f[1]~f[i-1]插入一颗trie树,对于f[i]我们只要在trie树中找到一条尽量与当前节点相反的路径,统计答案即可。注意每个二进制树的高位要靠近根节点。
代码
#include <cstdio>
#include <string>
#include <cstring>
#define N 300005
using namespace std;
struct trie
{
int nxt[2];
}tr[N*20];
struct arr
{
int to,nxt,w;
}a[N];
int n,l,cnt,tot,ls[N],f[N],b[50];
bool v[N];
void add(int x, int y, int z)
{
a[++l].to = y;
a[l].w = z;
a[l].nxt = ls[x];
ls[x] = l;
}
void dfs(int x)
{
v[x] = true;
for (int i = ls[x]; i; i = a[i].nxt)
if (!v[a[i].to])
{
f[a[i].to] = f[x] ^ a[i].w;
dfs(a[i].to);
}
}
void change(int x)
{
cnt = 0;
for (int i = 0; i <= 32; i++)
b[i] = 0;
while (x)
{
b[++cnt] = x % 2;
x/=2;
}
cnt++;
for (int i = cnt; i <= 32; i++)
b[cnt] = 0;
cnt = 32;
}
void ins(int x)
{
change(x);
int now = 0;
while (cnt)
{
if (!tr[now].nxt[b[cnt]])
{
tr[now].nxt[b[cnt]] = ++tot;
// tr[tot].nxt[1] = tr[tot].nxt[0] = 0;
}
now = tr[now].nxt[b[cnt]];
cnt--;
}
}
int count(int x)
{
int s = 0;
change(x);
int now = 0;
while (cnt)
{
if (tr[now].nxt[1 - b[cnt]])
{
s+=1 << (cnt - 1);
now = tr[now].nxt[1 - b[cnt]];
}
else now = tr[now].nxt[b[cnt]];
cnt--;
}
return s;
}
void clear()
{
for (int i = 0; i <= 3*n; i++)
{
ls[i] = 0;
f[i] = 0;
v[i] = false;
l = tot = cnt = 0;
}
memset(tr,0,sizeof tr);
memset(a,0,sizeof a);
}
int main()
{
while (~scanf("%d", &n))
{
clear();
for (int i = 1; i < n; i++)
{
int x,y,z;
scanf("%d%d%d", &x, &y, &z);
x++;y++;
add(x, y, z);
add(y, x, z);
}
dfs(1);
int ans = 0;
for (int i = 1; i <= n; i++)
{
int s = count(f[i]);
if (s > ans) ans = s;
ins(f[i]);
}
printf("%d\n", ans);
}
}