Loading

POJ3764 The xor-longest Path(异或/01Trie)

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

Hint

The xor-longest path is 0->1->2, which has length 7 (=3 ⊕ 4)

这题有LCA内味了。注意到异或的性质,设d[x]为根节点到x的路径的异或值,则x到y的异或值实际上就是d[x] xor d[y],因为根节点到LCA(x,y)的这段路径自己异或了两次相当于什么都没有变。因此问题转化为从d数组挑选两个数使得其异或值最大,就变成01字典树了。

坑点:多组输入,记得及时清空数组以及ans,tot等变量,数组开两倍建反向边。略微卡点时间,因此尽量采取快一点的写法和输入输出等。

#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstring>
#define N 100005
using namespace std;
int n,head[N],ver[2*N],Next[2*N],edge[2*N],ttot=0,d[N];

int trie[100005*31][2],tot=1,ans=0;
void add(int x,int y,int z)
{
    ver[++ttot]=y,edge[ttot]=z,Next[ttot]=head[x],head[x]=ttot;
}
void dfs(int x,int pre,int sum)
{
    int i;
    for(i=head[x];i;i=Next[i])
    {
        int y=ver[i],z=edge[i];
        if(y==pre) continue;
        d[y]=z^sum;
        dfs(y,x,d[y]);
    }
}
int fpow(int a,int b)
{
    int ans=1;
    for(;b;b>>=1)
    {
        if(b&1) ans=ans*a;
        a=a*a;
    }
    return ans;
}
void insert(int x)
{
    int p=1,k;
    for(k=30;k>=0;k--)
    {
        int temp=x&(1<<k)?1:0;
        if(trie[p][temp]==0) trie[p][temp]=++tot;
        p=trie[p][temp];
    }
}
int search(int x)//返回最大的异或值 
{
    int k,p=1,num=0;
    for(k=30;k>=0;k--)
    {
        int orip=p,temp=x&(1<<k)?1:0;
        p=trie[p][1-temp];//防止p被更改 
        if(p==0) 
        {
            p=trie[orip][temp];//退而求其次
        }
        else
        {
            num+=fpow(2,k);
        }
    }
    return num;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(head,0,sizeof(head));
        memset(Next,0,sizeof(Next));
        memset(edge,0,sizeof(edge));
        memset(ver,0,sizeof(ver));
        memset(trie,0,sizeof(trie));
        tot=1,ttot=0,ans=0;
        int i;
        for(i=1;i<=n-1;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        } 
        dfs(0,-1,0);
        for(i=0;i<n;i++)
        {
            insert(d[i]);
        }
        for(i=0;i<n;i++)
        {
            ans=max(ans,search(d[i]));
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2020-06-03 14:37  脂环  阅读(223)  评论(0编辑  收藏  举报