IT民工
加油!

建立字典树,树的结点记录根结点到该结点的连续异或值。

(a ^ c) ^ (b ^ c) == a ^ b 可得任意两结点的异或值,等于两结点之间这条路的连续异

或值。由此把每个结点的值插入01字典树,从二进制31~0位,并查找,尽可能的向

每一位的不同方向查找(这样异或这一位能得1),取最大值。位运算还得继续学习。

 

/*Accepted    44068K    875MS    C++    1756B    2012-08-02 16:10:05*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

const int MAXN = 210000;
typedef struct
{
    int to[2];
    int num;
}Trie;

Trie t[MAXN << 4];
int first[MAXN], next[MAXN], u[MAXN], v[MAXN], w[MAXN];
int tp, n, ans;

void insert(int x, int site, int bit)
{
    if(bit != -1)
    {
        if(t[site].to[x >> bit & 1] == -1)
            t[site].to[x >> bit & 1] = ++ tp;
        insert(x, t[site].to[x >> bit & 1], bit - 1);
    }
    else
    {
        t[site].num = x;
    }
}

void cal(int x, int site, int bit)
{
    if(-1 == bit)
    {
        int y = x ^ t[site].num;
        if(y > ans)
            ans = y;
    }
    else if(t[site].to[~ x >> bit & 1] != -1)
    {
        cal(x, t[site].to[~ x >> bit & 1], bit - 1);
    }
    else
    {
        cal(x, t[site].to[x >> bit & 1], bit - 1);
    }
}

void calc(int x)
{
    cal(x, 0, 31);
    insert(x, 0, 31);
}

void addedge(int u1, int v1, int w1, int e)
{
    next[e] = first[u1];
    first[u1] = e;
    u[e] = u1, v[e] = v1, w[e] = w1;
}

void ReadTree()
{
    int u1, v1, w1, e;
    memset(first, -1, sizeof (int) * (n + 1));
    for(e = 1; e < n; e ++)
    {
        scanf("%d%d%d", &u1, &v1, &w1);
        addedge(u1, v1, w1, e);
        addedge(v1, u1, w1, e + n);
    }
}

void build(int e, int p, int last)
{
    calc(last);
    while(e != -1)
    {
        if(v[e] != p)
            build(first[v[e]], u[e], w[e] ^ last);
        e = next[e];
    }
}

int main()
{
    while(scanf("%d", &n) == 1)
    {
        tp = ans = 0;
        memset(t, -1, sizeof (Trie)*((n + 1) << 5));
        ReadTree();
        build(first[u[1]], -1, 0);
        printf("%d\n", ans);
    }
    return 0;
}

 

 

 

 

posted on 2012-08-02 16:26  找回失去的  阅读(507)  评论(0编辑  收藏  举报