P4551 最长异或路径
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4551 最长异或路径相关的知识,希望对你有一定的参考价值。
题意:
给定一棵 n 个点的带权树,结点下标从 1 开始到 n。寻找树中找两个结点,求最长的异或路径。
异或路径指的是指两个结点之间唯一路径上的所有边权的异或。
题解:
我们指定1为根节点,T(u,v)表示u到v之间的路径的边权异或和,那么T(u,v)=T(root,u) Xor T(root,v)
所以我们可以将所有的T(root,u)插入到一个trie中,对每个T(root,u)快速求出和它异或最大的T(root,v)
从trie的根开始,如果能向和T(root,u)的当前位不同的子树走,就向那边走,否则没有选择
代码:
#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b);
typedef long long ll;
using namespace std;
//Fe~Jozky
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){
ll s=0,w=1ll;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
}
const int maxn=3e5+9;
int rtnum=1;
struct tree_01{
int cnt;
int ch[2];
void init(){
ch[0]=ch[1]=0;
cnt=0;
}
}tr[maxn<<4];
vector<pair<int,int> >vec[maxn];
int ans=0;
int dis[maxn];
void insert(int x){
int rt=1;
for(int i=30;i>=0;i--){
int c=((x>>i)&1);
if(tr[rt].ch[c]==0)
{
tr[rt].ch[c]=++rtnum;
// tr[rtnum].init();
}
rt=tr[rt].ch[c];
}
}
void get(int x){
int rt=1;
int cnt=0;
for(int i=30;i>=0;i--){
int c=((x>>i)&1);
if(tr[rt].ch[c^1]){
rt=tr[rt].ch[c^1];
cnt|=(1<<i);
}
else if(tr[rt].ch[c])rt=tr[rt].ch[c];
else break ;
}
ans=max(ans,cnt);
}
void dfs(int x,int fa){
insert(dis[x]);
get(dis[x]);
for(auto it:vec[x]){
int v=it.first;
int w=it.second;
if(v==fa)continue;
dis[v]=dis[x]^w;
dfs(v,x);
}
return ;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<n;i++){
int u,v,w;
cin>>u>>v>>w;
vec[u].push_back({v,w});
vec[v].push_back({u,w});
}
tr[1].init();
dis[1]=0;
dfs(1,0);
cout<<ans;
}
以上是关于P4551 最长异或路径的主要内容,如果未能解决你的问题,请参考以下文章