The xor-longest Path(01字典树—求树上连续区间的最大异或值)

版权声明:本文为博主原创文章,转载请说明出处。 https://blog.csdn.net/xianpingping/article/details/83108065

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:

_{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)

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;
}

猜你喜欢

转载自blog.csdn.net/xianpingping/article/details/83108065