POJ 3764 - The xor-longest Path - [DFS+字典树变形]

题目链接:http://poj.org/problem?id=3764

Time Limit: 2000MS  Memory Limit: 65536K

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) = \bigoplus_{e \in p}w(e)$

$\oplus$ 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 \oplus 4$

题意:

对一棵带权树,我们定义树上的某条路径 $p$ 的“异或长度”为该路径上所有边的边权的异或值。要求你找出树上“异或长度”最长的路径,并求出其“异或长度”。

题解:

显然对于树上任意节点 $x$,我们可以用DFS递推地求出 $dist[x] = dist[par[x]] \oplus w(par[x],x)$。

我们可以枚举所有路径的两个端点 $x,y$,其路径为 $x \sim LCA(x,y) \sim y$。

那么根据异或的性质,就有 $_{xor}length(x \sim y) = dist[x] \oplus dist[y]$,因为 $_{xor}length(root \sim LCA(x,y))$ 这一段同时出现在 $dist[x]$ 和 $dist[y]$ 中,异或之后即为 $0$,正好抵消掉了。

因此,问题就转化为对于长度为 $n$ 的序列 $dist[1] \sim dist[n]$,寻找某一对 $(x,y)$ 使得 $dist[x] \oplus dist[y]$ 最大,给出最大值。该问题即CH 1602 - The XOR Largest Pair - [字典树变形]

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e5+10;

int n;

struct Edge{
    int u,v,w;
    int next;
};
Edge E[2*maxn];
int head[maxn],ne;
void init()
{
    ne=0;
    memset(head,0,sizeof(head));
}
void addedge(int u,int v,int w)
{
    ++ne;
    E[ne].u=u, E[ne].v=v, E[ne].w=w;
    E[ne].next=head[u];
    head[u]=ne;
}

int d[maxn];
bool vis[maxn];
void dfs(int u)
{
    vis[u]=1;
    for(int i=head[u];i;i=E[i].next)
    {
        if(!vis[E[i].v])
        {
            d[E[i].v]=d[u]^E[i].w;
            dfs(E[i].v);
        }
    }
}

namespace Trie
{
    const int SIZE=maxn*32;
    int sz;
    struct TrieNode
    {
        int ed;
        int nxt[2];
    }trie[SIZE];
    void init()
    {
        sz=1;
        memset(trie,0,sizeof(trie));
    }
    void insert(int x)
    {
        int p=1;
        for(int k=30;k>=0;k--)
        {
            int ch=(x>>k)&1;
            if(trie[p].nxt[ch]==0) trie[p].nxt[ch]=++sz;
            p=trie[p].nxt[ch];
        }
    }
    int MaxXor(int x)
    {
        int res=0;
        int p=1;
        for(int k=30;k>=0;k--)
        {
            int ch=(x>>k)&1;
            if(trie[p].nxt[ch^1])
            {
                p=trie[p].nxt[ch^1];
                res|=1<<k;
            }
            else p=trie[p].nxt[ch];
        }
        return res;
    }
};

int main()
{
    while(cin>>n)
    {
        init();
        for(int i=1,u,v,w;i<n;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            addedge(u+1,v+1,w);
            addedge(v+1,u+1,w);
        }

        memset(vis,0,sizeof(vis));
        memset(d,0,sizeof(d));
        dfs(1);

        Trie::init();
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            Trie::insert(d[i]);
            ans=max(ans,Trie::MaxXor(d[i]));
        }
        cout<<ans<<endl;
    }
}

猜你喜欢

转载自www.cnblogs.com/dilthey/p/9932409.html