The xor-longest Path
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 10003 | Accepted: 2029 |
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)
Source
这道题就是利用异或的性质。
先预处理出1节点(默认为根节点)到其他所有节点的异或值。然后每一个点所拥有的异或值insert到字典树里,然后每一个点都找一个点使得异或值最大。因为w^gen^v^gen就是w到v的异或值,重复的路径就抵消了,这个思想在异或中经常用。本题复杂度是N*LOGN
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=100000+10;
int n,m;
int a[maxn];
int tree[32*maxn][2];
LL val[32*maxn];
int tot;
void insert_(LL d)
{
int root=0;
for(int i=31;i>=0;i--)
{
int id=(d>>i)&1;//获得这一个bit位的值
if(!tree[root][id])
tree[root][id]=++tot;
root=tree[root][id];
}
val[root]=d;
}
int find_(int d)
{
int ans=0;
int root=0;
for(int i=31;i>=0;i--)
{
int id=(d>>i)&1;
if(tree[root][id^1])
{
root=tree[root][id^1];///能找到跟他相反的就找
ans^=(1<<i);
}
else
root=tree[root][id];///找不到的话只能找跟当前位数一样的
}
return ans;
}
int tol;
int head[maxn];
struct edge{
int to,val;
int next;
}G[2*maxn];
void add(int u,int v,int w){
G[++tol].to=v;
G[tol].val=w;
G[tol].next=head[u];
head[u]=tol;
}
void dfs(int u,int p){
for(int i=head[u];i!=-1;i=G[i].next){
int to=G[i].to;
if(to==p)
continue;
a[to]=a[u]^G[i].val;
dfs(to,u);
}
}
int main()
{
int n,x,y,w;
while(scanf("%d",&n)!=EOF){
memset(tree,0,sizeof(tree));
tol=0;
tot=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=n-1;i++){
scanf("%d%d%d",&x,&y,&w);
add(x+1,y+1,w);
add(y+1,x+1,w);
}
dfs(1,0);
int ans=0;
for(int i=1;i<=n;i++){
insert_(a[i]);
}
for(int i=1;i<=n;i++){
ans=max(ans,find_(a[i]));
}
printf("%d\n",ans);
}
return 0;
}