最大异或对路径
原题链接:最大异或对路径
题目大意
给你(n)个关系,表示 (u,v) 两点间有一条边,且有边权,问异或和长度最大的路径的异或值是多少?
题目题解
和上一道题很像,但是需要转化一下思路,我们上一道题是两个点之间进行计算,那么这道题是不是也能这样计算呢?当然可以,但是需要转化模型,对于任意两点 (u, v) 而言,(u -> root) 和 (v->root) 都可以将其路径的异或值都算出来,我们这里假设 (u,v) 在根节点的同一个子树上,那么这两个点到根节点的路径一定有相交的路径,如果我们想得到 (u -> v) 就可以用下面的等式 ,我们这里假设 (d[x]) 为从(x)点到根节点的路径 那么就有 (d[u] wedge d[v] wedge d[lca(u,v)] wedge d[lca(u,v)]) 又因为异或满足结合律,于是可得最终结果为 (d[u]wedge d[v]) ,于是我们就可以将每个点到根节点的结果预处理出来,最终我们就将模型转化到点上了,建个trie树,跑一遍就好
代码如下
//#define fre yes
#include <cstdio>
const int N = 100005;
int head[N << 1], to[N << 1], ver[N << 1], edge[N];
struct Node {
int son[26];
} trie[N * 30];
int tot;
void addedge(int x, int y, int z) {
ver[tot] = y;
edge[tot] = z;
to[tot] = head[x];
head[x] = tot++;
}
void dfs(int u, int fa, int sum) {
a[u] = sum;
for (int i = head[u]; ~i; i = to[i]) {
int v = ver[i];
if(v != fa) {
dfs(v, u, sum ^ edge[i]);
}
}
}
int idx;
void Insert(int x) {
int rt = 0;
for (int i = 30; i >= 0; i--) {
int id = x >> i & 1;
if(!trie[rt].son[id]) trie[rt].son[id] = ++idx;
rt = trie[rt].son[id];
}
}
int main() {
memset(head, -1, sizeof(head));
static int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
addedge(u, v, w);
addedge(v, u, w);
}
dfs(0, -1, 0);
for (int i = 1; i <= n; i++) Insert(a[i]);
int ans = 0;
for (int i = 1; i <= n; i++) ans = std::max(ans, Search(a[i]));
printf("%d
", ans);
return 0;
}