The XOR-longest Path
题目大意
给定一棵树, 让你求树上异或和最大的简单路径的异或和
分析
想要异或和最大, 那么我们想要的显然是贪心, 那就是尽量让他们在二进制下不相同
这样考虑的话, 我们可以想到的是字典树, 从高次项向低处贪心, 能保证最值
那么还有一个问题, 如何求一个简单路径的异或值?
我们又可以想到关于异或的优良性质:
就是说, 可以随机找一个根, 求到其他所有结点的链的路径异或和
如果我们要求的是, 那么它就可以十分简单的表示为
那么我们把所有的从根开始的路径插入到字典树中, 暴力查询跟新答案就好惹
#include <cstdio> const int Maxn = 100000 + 5; int Tree[Maxn * 31][2], Id; int Xor[Maxn]; int N, U, V, C, Ans; int Head[Maxn], Next[Maxn << 1], Edge[Maxn << 1], W[Maxn << 1], Cur; inline void AddEdge(int U, int V, int C) { Next[++Cur] = Head[U]; Head[U] = Cur; Edge[Cur] = V; W[Cur] = C; } inline void Insert(int X, int Rt = 0) { for (int i = 1 << 30; i; i >>= 1) { bool F = X & i; if (!Tree[Rt][F]) Tree[Rt][F] = ++Id; Rt = Tree[Rt][F]; } } inline int Query(int X, int Rt = 0, int Ans = 0) { for (int i = 1 << 30; i; i >>= 1) { bool F = X & i; if (Tree[Rt][!F]) Ans += i, Rt = Tree[Rt][!F]; else Rt = Tree[Rt][F]; } return Ans; } void DFS(int U, int F) { for (int i = Head[U]; i; i = Next[i]) { if (Edge[i] == F) continue; Xor[Edge[i]] = Xor[U] ^ W[i]; DFS(Edge[i], U); } } inline int max(int a, int b){return a > b ? a : b;} int main() { scanf("%d", &N); for (int i = 1; i < N; ++i) { scanf("%d %d %d", &U, &V, &C); AddEdge(U, V, C), AddEdge(V, U, C); } DFS(1, 1); for (int i = 1; i <= N; ++i) Insert(Xor[i]); for (int i = 1; i <= N; ++i) Ans = max(Ans, Query(Xor[i])); printf("%d\n", Ans); }