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);
} 
京公网安备 11010502036488号