The xor-longest Path
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 6954 Accepted: 1481
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)
题意:
给一棵树,每条路上有边权,求两点之间异或和最大是多少。
分析:
求两点之间的异或和显然不好求。但对每个节点,求它到根节点的异或和dis[i]显然是没问题的。
而两点之间的异或和就可以用dis[u]|dis[v];
接下来就是Trie树的部分了。
求异或和最大显然是Trie树的典型应用。对每个数查询的时候,从高位到低位,如果它的这一位是1的话,我们就贪心地选择0的那一条路,如果没有的为0的那边,才走为1的那条路。反之。然后将这个数插入Trie树中。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
#define ms(x,y) memset(x,y,sizeof(x))
using namespace std;
const int N = 400010;
int n;
int num=0,head[N];
inline int Max(int a,int b){
return a>b?a:b;
}
struct node{
int pre,u,v,w;
}edge[N*4];
void addedge(int from,int to,int w){
num++;
edge[num].pre=head[from];
edge[num].u=from;
edge[num].v=to;
edge[num].w=w;
head[from]=num;
}
int tt=0;
struct Trie{
int nxt[2];
int num[2];
void newnode(){
ms(num,0);}
}t[N*4];
void add(int x){
int root=0,cnt;
for(int i=30;i>=0;i--){
if(x&(1<<i)) cnt=1;
else cnt=0;
if(!t[root].nxt[cnt]){
t[root].nxt[cnt]=++tt;
t[tt].newnode();
}
root=t[root].nxt[cnt];
}
}
int Getresult(int x){
int ans=0,cnt,root=0;
for(int i=30;i>=0;i--){
if(x&(1<<i)) cnt=0;
else cnt=1;
if(t[root].nxt[cnt]){
ans|=(1<<i);
root=t[root].nxt[cnt];
}
else root=t[root].nxt[!cnt];
}
return ans;
}
bool vis[N];
int dis[N];
void dfs(int u,int w){
vis[u]=true;dis[u]=w;
for(int i=head[u];i;i=edge[i].pre){
int v=edge[i].v;
if(vis[v]) continue;
dfs(v,w^edge[i].w);
}
}
int ans;
void update(){
ms(dis,0);ms(vis,0);ms(head,0);ms(t,0);
t[0].newnode();tt=0,ans=-1;
}
int main(){
while(scanf("%d",&n)!=EOF){
update();
for(register int i=1;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
dfs(0,0);
for(register int i=0;i<n;i++){
ans=Max(ans,Getresult(dis[i]));
add(dis[i]);
}
printf("%d\n",ans);
}
return 0;
}