poj3764-The xor-longest Path

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)

题意:求树上两点路径的异或和的最大值

用d[x]表示根到x路径上所有边权的异或和,由异或的性质,x到y路径上所有边权的异或和等于d[x] xor d[y],所以就是在d[0]-d[n-1]中找两个数,使得异或之后最大。
把每个整数看作长度为31的01串(数值较小的在前面补0),然后插入到一棵字典树中
每次查找一个数,先尝试沿着与当前位相反的字符指针向下访问,如果没有就访问相同的,这样构造出来的一定是与当前查找的数做xor运算结果最大的。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
//#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+100;
int n,cnt,tot;
int last[N],d[N];
struct tree{
    int v,nex,w;}t[N*2];
int trie[N*32][2];
void add(int x,int y,int z)
{
    cnt++;
    t[cnt].v=y;
    t[cnt].nex=last[x];
    last[x]=cnt;
    t[cnt].w=z;
}
void dfs(int x,int fa,int dis)
{
    d[x]=dis;
    for (int i=last[x];i;i=t[i].nex)
    {
        if (t[i].v==fa) continue;
        dfs(t[i].v,x,dis^t[i].w);
    }
}

void Insert(int x)
{
    int p=0,now;
    for (int i=31;i>=0;i--)
    {
        now=(x>>i)&1;
        if (!trie[p][now]) trie[p][now]=++tot;
        p=trie[p][now];
    }
}
int fund(int x)
{
    int p=0,now,ret=0;
    for (int i=31;i>=0;i--)
    {
        now=!((x>>i)&1);
        ret<<=1;
        if (trie[p][now])
        {
            p=trie[p][now];
            ret++;
        }
        else p=trie[p][!now];
    }
    return ret;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(last,0,sizeof(last));
        memset(trie,0,sizeof(trie));
        cnt=0; tot=0;

        int x,y,z;
        for (int i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z); add(y,x,z);
        }
        d[0]=0;
        dfs(0,-1,0);

        int ans=0;
        for (int i=0;i<n;i++) Insert(d[i]);
        for (int i=0;i<n;i++) ans=max(ans,fund(d[i]));
        printf("%d\n",ans);
    }

    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/tetew/p/9677430.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值