POJ 3764 The xor-longest Path

The xor-longest Path
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 4778 Accepted: 1036

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)


解题思路:

求树上异或值最大的一条路径,首先通过DFS求出根节点到每个节点i的路径的异或值rs[i]。则u到v的路径的异或值就是rs[u] ^ rs[v],问题转化为从n个数中选出两个数使异或值最大,建立字母树,贪心求解。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <algorithm>
#define LL long long 
using namespace std;
const int MAXN = 100000 + 10;
int read()
{
    int x = 0, f = 1; char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f *= -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    return x * f;
}
struct Edge
{
    int to,  next, w;
}edge[MAXN<<1];
int tot, head[MAXN];
int vis[MAXN], rs[MAXN], u, v, w, N;
void init()
{
    tot = 0;
    memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int w)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    edge[tot].w = w;
    head[u] = tot++;
}
void dfs(int x)
{
    if(vis[x]) return ;
    vis[x] = 1;
    for(int i=head[x];i!=-1;i=edge[i].next)
    {
        int v = edge[i].to, w = edge[i].w;
        if(!vis[v])
        {
            rs[v] = rs[x] ^ w;
            dfs(v);
        }
    }
}
int Next[3000000 + 10][2], End[3000000 + 10];
int root, L;
int newnode()
{
    for(int i=0;i<2;i++)
        Next[L][i] = -1;
    End[L] = -1;
    return L++;
}
int cal(int x)
{
    int cur = 0;
    for(int i=30;i;i--)
    {
        int k = ((1 << i) & x) ? 0 : 1;
        if(Next[cur][k] != -1) cur = Next[cur][k];
        else cur = Next[cur][1 - k];
    }
    return (x ^ End[cur]);
}
int main()
{
    while(scanf("%d", &N)!=EOF)
    {
        init();
        for(int i=1;i<N;i++)
        {
            scanf("%d%d%d", &u, &v, &w);
            u++; v++;
            addedge(u, v, w); addedge(v, u, w);
        }
        int rt = 1;
        memset(vis, 0, sizeof(vis)); memset(rs, 0, sizeof(rs));
        dfs(rt);
        //for(int i=1;i<=N;i++) cout << rs[i] << ' '; cout << endl;
        L = 0, root = newnode();
        for(int i=1;i<=N;i++)
        {
            int x = rs[i];
            int now = 0;
            for(int j=30;j;j--)
            {
                int k = ((1 << j) & x) ? 1 : 0;
                if(Next[now][k] == -1) Next[now][k] = newnode();
                now = Next[now][k];
            }
            End[now] = x;
        }
        int ans = 0;
        for(int i=1;i<=N;i++) ans = max(ans, cal(rs[i]));
        printf("%d\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值