建立字典树,树的结点记录根结点到该结点的连续异或值。
由(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; }