POJ 3764 The xor-longest Path 字典树 异或性质

来源:互联网 发布:淘宝网民族风帽子 编辑:程序博客网 时间:2024/03/29 17:15

题意:给出一棵树,每条边上都有权值。求在树上的一条路径,使在这条路径上的异或和最大。

思路:对于异或,我们要考虑其二进制分解。

            因为异或满足结合性,所以xorsum[u,v] = xorsum[0,u] ^ xorsum[0,v];我们将任意一点作为根,这样xorsum[0.v]就能dfs求出。

            同样,由于上面的公式,对于任意一点u的到其他路径的异或和的最大值,其实就是相当于查询其他的所有的xorsum[0,v]和xorsum[0,v]的最大值。这个转化成了在N个数中查找和给定数异或和最大的值。这个可以用字典树来加速查询,复杂度为O(32)。

复杂度:O(32N).

代码如下:

#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int MAX = 100010;struct edge{    int to,w;    edge(){}    edge(int t, int ww):w(ww),to(t){}} edges[MAX<<1];int head[MAX],nxt[MAX<<1],tot,N,xo[MAX];char str[40];void init(){    tot = 0;    memset(head,-1,sizeof(head));}void addedge(int u, int v, int w){    edges[tot] = edge(v,w);    nxt[tot] = head[u], head[u] = tot++;    edges[tot] = edge(u,w);    nxt[tot] = head[v], head[v] = tot++;}void dfs(int u, int fa){    for(int i = head[u]; ~i; i = nxt[i]){        edge & e = edges[i];        if(e.to == fa) continue;        xo[e.to] = xo[u] ^ e.w;        dfs(e.to,u);    }}void tostr(int n){    for(int i = 31; i >= 0; --i)        str[i] = n % 2 + '0', n >>= 1;    str[32] = 0;}int tonum(){    int t = 1,ans = 0;    for(int i = 31; i >= 0; --i)        ans += (str[i] - '0') * t, t *= 2;    return ans;}struct Trie{    static const int CHARSET = 2;    static const int BASE  = '0';    static const int MAXNODE = 4000000;    int child[MAXNODE][CHARSET];    int v[MAXNODE];    int root,sz;    int id;    Trie(){init();}    void init(){        root = 1,sz = 1,id = 1;        memset(child[1],0,sizeof(child[1]));        memset(v,0,sizeof(v));    }    void insert(char * s){        int * cur = & root;        for(char *p = s; *p; ++p){            cur = &child[*cur][*p - BASE];            if(*cur == 0){                *cur = ++sz;                memset(child[*cur],0,sizeof(child[*cur]));            }        }    }    int query(int num){        tostr(num);        int * cur = & root;        for(char * p = str; *p ; ++p){            int c = (*p - BASE) ^ 1;            if(child[*cur][c] != 0){                *p += c;                cur = &child[*cur][c];            }            else{                cur = &child[*cur][c^1];                *p = '0';            }        }        return tonum();    }} trie;int main(void){    int u,v,w;    //freopen("input.txt","r",stdin);    while(~scanf("%d",&N)){        init();        for(int i = 0; i < N - 1; ++i){            scanf("%d%d%d",&u,&v,&w);            addedge(u,v,w);        }        xo[0] = 0;        dfs(0,-1);        trie.init();        for(int i = 0; i < N; ++i){            tostr(xo[i]);            trie.insert(str);        }        int ans = 0;        for(int i = 0; i < N; ++i)            ans = max(ans,trie.query(xo[i]));        printf("%d\n",ans);    }    return 0;}


0 0