poj3764 The xor-longest Path(trie)

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:
这里写图片描述
{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

题意,给出一棵树,每条边有边权,选择两个点x,y,把从x到y的路径上所有边权异或起来,求结果最大多少。

分析:设f[i]为从根节点到i的路径上所有边权异或起来的结果,显然x到y的结果就是f[x]^f[y],那么只需求所有f[x]^f[y]中的最大值。我们可以把每个f[i]看作长度为32的二进制数,不够的前面补0,将f[1]~f[i-1]插入一颗trie树,对于f[i]我们只要在trie树中找到一条尽量与当前节点相反的路径,统计答案即可。注意每个二进制树的高位要靠近根节点。

代码

#include <cstdio>
#include <string>
#include <cstring>
#define N 300005
using namespace std;

struct trie
{
    int nxt[2];
}tr[N*20];
struct arr
{
    int to,nxt,w;
}a[N];
int n,l,cnt,tot,ls[N],f[N],b[50];
bool v[N];

void add(int x, int y, int z)
{
    a[++l].to = y;
    a[l].w = z;
    a[l].nxt = ls[x];
    ls[x] = l;
}

void dfs(int x)
{
    v[x] = true;
    for (int i = ls[x]; i; i = a[i].nxt)
        if (!v[a[i].to])
        {
            f[a[i].to] = f[x] ^ a[i].w;
            dfs(a[i].to);
        }
}

void change(int x)
{
    cnt = 0;
    for (int i = 0; i <= 32; i++)
        b[i] = 0;
    while (x) 
    {
        b[++cnt] = x % 2;
        x/=2;
    }
    cnt++;
    for (int i = cnt; i <= 32; i++)
        b[cnt] = 0;
    cnt = 32;
}

void ins(int x)
{
    change(x);
    int now = 0;
    while (cnt)
    {
        if (!tr[now].nxt[b[cnt]]) 
        {
            tr[now].nxt[b[cnt]] = ++tot;
        //  tr[tot].nxt[1] = tr[tot].nxt[0] = 0;
        }
        now = tr[now].nxt[b[cnt]];
        cnt--;
    }
}

int count(int x)
{
    int s = 0;
    change(x);
    int now = 0;
    while (cnt)
    {
        if (tr[now].nxt[1 - b[cnt]])
        {
            s+=1 << (cnt - 1);
            now = tr[now].nxt[1 - b[cnt]];
        }
        else now = tr[now].nxt[b[cnt]];
        cnt--;
    }
    return s;
}

void clear()
{
    for (int i = 0; i <= 3*n; i++)
    {
        ls[i] = 0;
        f[i] = 0;
        v[i] = false;
        l = tot = cnt = 0;
    }
    memset(tr,0,sizeof tr);
    memset(a,0,sizeof a);
}

int main()
{
    while (~scanf("%d", &n))
    {
        clear();
        for (int i = 1; i < n; i++)
        {
            int x,y,z;
            scanf("%d%d%d", &x, &y, &z);
            x++;y++;
            add(x, y, z);
            add(y, x, z);
        }
        dfs(1);
        int ans = 0;
        for (int i = 1; i <= n; i++)
        {
            int s = count(f[i]);
            if (s > ans) ans = s;
            ins(f[i]);
        }
        printf("%d\n", ans);
    }
}

猜你喜欢

转载自blog.csdn.net/zhanghaoxian1/article/details/81771552