[BZOJ1954][Pku3764]The xor-longest Path
[BZOJ1954][Pku3764]The xor-longest Path
试题描述
给定一棵n个点的带权树,求树上最长的异或和路径
输入
The input contains several test cases. The first line of each test case contains an integer n(1<=n<=100000), The following n-1 lines each contains three integers u(0 <= u < n),v(0 <= v < n),w(0 <= w < 2^31), which means there is an edge between node u and v of length w.
输出
For each test case output the xor-length of the xor-longest path.
输入示例
4 1 2 3 2 3 4 2 4 6
输出示例
7
数据规模及约定
见“输入”
题解
这题中英文切换的。。。
一开始理解错题意了。。。把边权看成了点权,搞得还以为要点分治 + trie 树。。。
如果是边权,那么不难发现 xor(u, v)(即 u 到 v 的亦或和)= d[u] ^ d[v],d[u] 表示 u 到根节点的亦或和。
于是搞出 d 数组,把每个数插到 trie 中,然后对每个 d[i] 查询一遍 trie 树中与 d[i] 亦或的最大值,方法是贪心,从高位到底位尽量往与当前二进制位不同的方向走。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <algorithm> #include <vector> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); } return x * f; } #define maxn 100010 #define maxm 200010 #define maxnode 3200010 int n, m, head[maxn], nxt[maxm], to[maxm], dist[maxm], val[maxn]; void AddEdge(int a, int b, int c) { to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m; swap(a, b); to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m; return ; } int rt, ToT, ch[maxnode][2]; bool num[32]; void insert(int x) { int cnt = 0; memset(num, 0, sizeof(num)); while(x) num[++cnt] = x & 1, x >>= 1; cnt = 31; int u = rt; for(int i = cnt; i; i--) { if(!ch[u][num[i]]) ch[u][num[i]] = ++ToT; u = ch[u][num[i]]; } return ; } void build(int u, int fa, int v) { insert(v); val[u] = v; for(int e = head[u]; e; e = nxt[e]) if(to[e] != fa) build(to[e], u, v ^ dist[e]); return ; } int query(int x) { int cnt = 0; memset(num, 0, sizeof(num)); while(x) num[++cnt] = x & 1, x >>= 1; cnt = 31; int u = rt, ans = 0; for(int i = cnt; i; i--) if(ch[u][num[i]^1]) ans = ans << 1 | 1, u = ch[u][num[i]^1]; else ans <<= 1, u = ch[u][num[i]]; return ans; } int main() { n = read(); for(int i = 1; i < n; i++) { int a = read(), b = read(), c = read(); AddEdge(a, b, c); } ToT = rt = 1; build(1, 0, 0); int ans = 0; for(int i = 1; i <= n; i++) ans = max(ans, query(val[i])); printf("%d\n", ans); return 0; }