Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 4778 | Accepted: 1036 |
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
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)
解题思路:
求树上异或值最大的一条路径,首先通过DFS求出根节点到每个节点i的路径的异或值rs[i]。则u到v的路径的异或值就是rs[u] ^ rs[v],问题转化为从n个数中选出两个数使异或值最大,建立字母树,贪心求解。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <algorithm>
#define LL long long
using namespace std;
const int MAXN = 100000 + 10;
int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f *= -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
struct Edge
{
int to, next, w;
}edge[MAXN<<1];
int tot, head[MAXN];
int vis[MAXN], rs[MAXN], u, v, w, N;
void init()
{
tot = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int w)
{
edge[tot].to = v;
edge[tot].next = head[u];
edge[tot].w = w;
head[u] = tot++;
}
void dfs(int x)
{
if(vis[x]) return ;
vis[x] = 1;
for(int i=head[x];i!=-1;i=edge[i].next)
{
int v = edge[i].to, w = edge[i].w;
if(!vis[v])
{
rs[v] = rs[x] ^ w;
dfs(v);
}
}
}
int Next[3000000 + 10][2], End[3000000 + 10];
int root, L;
int newnode()
{
for(int i=0;i<2;i++)
Next[L][i] = -1;
End[L] = -1;
return L++;
}
int cal(int x)
{
int cur = 0;
for(int i=30;i;i--)
{
int k = ((1 << i) & x) ? 0 : 1;
if(Next[cur][k] != -1) cur = Next[cur][k];
else cur = Next[cur][1 - k];
}
return (x ^ End[cur]);
}
int main()
{
while(scanf("%d", &N)!=EOF)
{
init();
for(int i=1;i<N;i++)
{
scanf("%d%d%d", &u, &v, &w);
u++; v++;
addedge(u, v, w); addedge(v, u, w);
}
int rt = 1;
memset(vis, 0, sizeof(vis)); memset(rs, 0, sizeof(rs));
dfs(rt);
//for(int i=1;i<=N;i++) cout << rs[i] << ' '; cout << endl;
L = 0, root = newnode();
for(int i=1;i<=N;i++)
{
int x = rs[i];
int now = 0;
for(int j=30;j;j--)
{
int k = ((1 << j) & x) ? 1 : 0;
if(Next[now][k] == -1) Next[now][k] = newnode();
now = Next[now][k];
}
End[now] = x;
}
int ans = 0;
for(int i=1;i<=N;i++) ans = max(ans, cal(rs[i]));
printf("%d\n", ans);
}
return 0;
}