【bzoj1954】【The xor-longest Path】【trie树】

Description

 给定一棵n个点的带权树,求树上最长的异或和路径

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
1 2 3
2 3 4
2 4 6

Sample Output

7

HINT

The xor-longest path is 1->2->3, which has length 7 (=3 ⊕ 4) 
注意:结点下标从1开始到N....

题解:两个点到根的异或和异或一下就是这两个点之间的异或和。

           所以只要统计出所有点到根的异或和,放到trie树里面。

           然后在trie树里面依次查询每个点的最大异或即可。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 100010
using namespace std;
int point[N],next[N<<1],x,y,v,cnt,n,ans,a[N];
struct use{int st,en,v;}e[N<<1];
struct trie{
  int ch[N*30][2],cnt;
  void insert(int x){
    int now(0);
    for (int i=30;i>=0;i--){
      int t=x&(1<<i);t>>=i;
      if (!ch[now][t]) ch[now][t]=++cnt;    
      now=ch[now][t]; 
    }
  }
  int query(int x){
    int now(0),temp(0);
    for (int i=30;i>=0;i--){
      int t=x&(1<<i);t>>=i;
      if (ch[now][t^1]) temp+=1<<i,now=ch[now][t^1];
      else now=ch[now][t];  
    }
    return temp;
  }
}trie;
void add(int x,int y,int v){
  next[++cnt]=point[x];point[x]=cnt;e[cnt].en=y;e[cnt].v=v; 
}
void dfs(int x,int fa){
  for (int i=point[x];i;i=next[i])
   if (e[i].en!=fa){
     a[e[i].en]=a[x]^e[i].v;
     dfs(e[i].en,x);
   }
}
int main(){
  scanf("%d",&n);
  for (int i=1;i<n;i++){
    scanf("%d%d%d",&x,&y,&v);
    add(x,y,v);add(y,x,v);
  } 
  dfs(1,0);
  for (int i=1;i<=n;i++) trie.insert(a[i]);
  for (int i=1;i<=n;i++)
    ans=max(ans,trie.query(a[i]));
  cout<<ans<<endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值