P4551 最长异或路径(01trie模板)
Posted xcxc82
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4551 最长异或路径(01trie模板)相关的知识,希望对你有一定的参考价值。
大致题意
给定一棵(n)个点的带权树,求最长的异或路径。
异或路径指的是指两个结点之间唯一路径上的所有边权的异或
(1≤n≤100000)
分析
01trie模板
设(f_i)表示从根节点到(i)节点的异或路径,有显然的递推公式:(f_v = f_{fa}⊕edge.w)
根据异或的性质,(x)到(y)之间的异或路径即为(f_v⊕f_u)((a⊕a = 0),即路径上重合的一部分恰好抵消)
于是可以将每个(f_i)的二进制串从左到右插入到一颗(trie)树中,并在查询时尽可能地往与当前位相反的指针走即可
(code)
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100010;
struct e{
int u,v,w,next;
}edge[MAXN<<1];
int head[MAXN<<1],cnt = 0;
void add(int u,int v,int w){
++cnt;
edge[cnt].w = w;
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
int n,ans = 0;
int child[MAXN*40][2],tot = 1;
int a[MAXN];
void dfs(int u,int fa){
for(int i=head[u];i;i=edge[i].next){
int v = edge[i].v;
if(v==fa) continue;
a[v] = a[u]^edge[i].w;
dfs(v,u);
}
}
void insert(int a){
int p = 1;
for(int i=30;i>=0;i--){
int now = a>>i&1;
if(!child[p][now]) child[p][now] = ++tot;
p = child[p][now];
}
}
void findmax(int a){
int res = 0;
int p = 1;
for(int i=30;i>=0;i--){
int now = a>>i&1;
if(child[p][now^1]){
res|=1<<i;
p = child[p][now^1];
}
else{
p = child[p][now];
}
}
ans = max(ans,res);
}
int main(){
cin>>n;
for(int i=1;i<=n-1;i++){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
dfs(1,0);
for(int i=1;i<=n;i++){
insert(a[i]);
findmax(a[i]);
}
cout<<ans;
}
以上是关于P4551 最长异或路径(01trie模板)的主要内容,如果未能解决你的问题,请参考以下文章