poj3764 The xor-longest Path
TRIE树的经典应用:最大XOR问题
要求一个数与一堆数之中的最大XOR值
我们把一堆数建立一个trie树(按照二进制),那么最大XOR就是从trie顶开始,每一步都试图逆着这个数走,即可求得。
求一堆数中的最大xor呢?
就是每次insert前ask一下,更新答案。
那么本题呢?
考虑选定一个根,那么xor(i, j) = xor(root, i) ^ xor(root, j)
因为a ^ a = 0, a ^ 0 = a。
对于i, j来说,lca以上的路径会被抵消掉。
这样就是求max(xor(root, i), xor(root, j))了。
这样我们就按照开头所述方法来处理xor(root, i)即可。
1 #include <cstdio> 2 #include <cstring> 3 4 typedef long long LL; 5 6 const int N = 1000010; 7 8 int n; 9 10 inline void max(LL &a, LL b) { 11 if(a < b) a = b; 12 return; 13 } 14 15 struct Trie { 16 int s[N][2], top; 17 inline void clear() { 18 memset(s, 0, sizeof(s)); 19 top = 1; 20 return; 21 } 22 inline void insert(LL k) { 23 int p = 0; 24 for(int i = 31; i >= 0; i--) { 25 int f = (k >> i) & 1; 26 if(!s[p][f]) { 27 s[p][f] = ++top; 28 } 29 p = s[p][f]; 30 } 31 return; 32 } 33 inline LL maxor(LL k) { 34 LL ans = 0;int p = 0; 35 for(int i = 31; i >= 0; i--) { 36 int f = !((k >> i) & 1); 37 if(s[p][f]) { 38 p = s[p][f]; 39 ans = (ans << 1) | 1; 40 } 41 else { 42 p = s[p][f ^ 1]; 43 ans = ans << 1; 44 } 45 } 46 return ans; 47 } 48 }trie; 49 50 struct Edge { 51 int v, nex; 52 LL len; 53 }edge[N]; int top; 54 int e[N]; 55 LL val[N]; 56 bool vis[N]; 57 58 inline void add(int x, int y, LL z) { 59 ++top; 60 edge[top].v = y; 61 edge[top].len = z; 62 edge[top].nex = e[x]; 63 e[x] = top; 64 return; 65 } 66 67 void DFS(int k, int now) { 68 vis[k] = 1; 69 val[k] = now; 70 for(int i = e[k]; i; i = edge[i].nex) { 71 int ed = edge[i].v; 72 if(vis[ed]) continue; 73 DFS(ed, now ^ edge[i].len); 74 } 75 return; 76 } 77 78 int main() { 79 int x, y; 80 LL z; 81 while(scanf("%d", &n) != EOF) { 82 trie.clear(); 83 top = 0; 84 memset(e, 0, sizeof(e)); 85 memset(vis, 0, sizeof(vis)); 86 87 for(int i = 1; i < n; i++) { 88 scanf("%d%d%lld", &x, &y, &z); 89 x++; 90 y++; 91 add(x, y, z); 92 add(y, x, z); 93 } 94 DFS(1, 0); 95 96 LL ans = -1; 97 for(int i = 1; i <= n; i++) { 98 max(ans, trie.maxor(val[i])); 99 trie.insert(val[i]); 100 } 101 printf("%lld\n", ans); 102 } 103 104 105 return 0; 106 }