给定一颗N个节点的树,树上的每条边都有一个权值。从树中选择两个点x和y,把x到y的路径上的所有边权xor起来,得到的结果最大是多少?


我们知道x到y的最短路是d[x]+d[y]-2*d[rt],其中rt是最近公共祖先的点。同样我们可以对树进行一次DFS,求出所有d[x]表示根到x的xor值。与最短路不同的是x到y的xor值是d[x]^d[y],因为d[x]^d[y]^d[rt]^d[rt]=d[x]^d[y]。


所以问题就变成了从d[0]~d[n-1]这n个数中选出两个点,使得异或的结果最大。可以用字典树求解。把每个整数看成是长度32的二进制01串,把数列插入字典树中。对于每次检索,尽量走与Ai当前位相反的字符指针,但如果没有这个相反的指针,那么只好访问相同的字符指针。可以知道这样的结果异或最优。


注意这题字典树SIZE的选择,SIZE是p的上限,而p是节点的个数,这个节点数的上限是100000(个最多不同的数)×31(每个数的节点个数)。

代码如下:

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

const int maxn=233333;
int head[maxn],nxt[maxn],to[maxn],val[maxn];
int tot;
int d[maxn];
int x,y,z,n;
int tto,trie[100000*31][2];
void init() {
    tot=0;
    memset(head,-1,sizeof head);
    tto=1;
    memset(trie,0,sizeof trie);
}
void add(int x,int y,int z) {
    to[tot]=y;
    val[tot]=z;
    nxt[tot]=head[x];
    head[x]=tot++;
}
void dfs(int x,int fa) {
    for(int i=head[x]; ~i; i=nxt[i]) {
        if(to[i]==fa)
            continue;
        d[to[i]]=d[x]^val[i];
        dfs(to[i],x);
    }
}
int search(int x) {
    int k=31,tx=0,p=1;
    int ret=0;
    for(; ~k; --k) {
        tx=x>>k&1;
        if(trie[p][!tx]==0) {
            ret|=tx<<k;
            p=trie[p][tx];
        } else {
            ret|=(!tx)<<k;
            p=trie[p][!tx];
        }
    }
    return ret;
}
void insert(int x) {
    int k=31,tx=0,p=1;
    for(; ~k; --k) {
        tx=x>>k&1;
        if(trie[p][tx]==0)
            trie[p][tx]=++tto;
        p=trie[p][tx];
    }
}
int main() {
    while(~scanf("%d",&n)) {
        init();
        for(int i=1; i<n; ++i) {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        dfs(0,-1);
        /*
        for(int i=0;i<n;++i)
            printf("%d ",d[i]);
        puts("");
        */
        int ans=0;
        insert(d[0]);
        for(int i=1; i<n; ++i) {
            ans=max(ans,d[i]^search(d[i]));
            insert(d[i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted on 2018-04-28 13:21  chagin  阅读(189)  评论(0编辑  收藏  举报