1012 - trie树&树上异或 - The XOR Longest Path(POJ 3764)

本文介绍了一种解决树形结构中寻找两节点间边权异或最大值的问题,通过预处理得到每个节点到根节点路径上的边权异或和,再利用Trie树查询异或最大值,实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

 

题意

给定一个有n个节点的树,每条边上有个边权,从树中任选两个节点 x 和 y ,把 x 到 y 的路径上所有边权xor起来,求最大值

 

分析

xor???有意思,还记得异或的自反性吗(a^b^b=a,a^0=a)

我们发现若将 x 到根路径上的所有边权异或起来,记作 d[x];y 到根路径上的所有边权异或起来,记作 d[y]

那么 d[x] xor d[y] 就是 x 到 y 的路径上所有边权xor起来的值

为什么呢?

因为  x  到根路径上(假设dep[x]>dep[y])和 y 到根路径上重复的边,在xor的时候就没了(异或两次相当于没有异或)

那我们就可以预处理出所有的 d[i]

然后现在问题就转化为求序列d[1]~d[n]中任意两个数异或起来的最大值

就可以用上一篇博客的方法了

 

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100009
#define in read()
using namespace std;
inline int read(){
	char ch;int f=1,res=0;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
	while(ch>='0'&&ch<='9'){
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	}
	return f==1?res:-res;
}
int n,d[N];
int nxt[N<<1],head[N],to[N<<1],w[N<<1],cnt=0;
void add(int x,int y,int z){
	nxt[++cnt]=head[x];head[x]=cnt;
	to[cnt]=y;w[cnt]=z;
}
void dfs(int u,int fu){
	for(int e=head[u];e;e=nxt[e]){
		int v=to[e];
		if(v==fu) continue;
		d[v]=(d[u]^w[e]);
		dfs(v,u);
	}
}
int trie[N<<5][2],tot=0;
void insert(int x){
	int pos=0;
	for(int i=31;i>=0;--i){
		int c;
		if(x&(1ll<<i)) c=1;
		else c=0;
		if(!trie[pos][c]) trie[pos][c]=++tot;
		pos=trie[pos][c];
	}
}
int query(int x){
	int pos=0,res=0;
	for(int i=31;i>=0;--i){
		int c;
		if(x&(1ll<<i)) c=1;
		else c=0;
		if(trie[pos][c^1]) pos=trie[pos][c^1],res=res|(1ll<<i);
		else pos=trie[pos][c];
	}
	return res;;
}
int main(){
	while(scanf("%d",&n)!=EOF){
		int i,j,k;
		cnt=0;memset(head,0,sizeof(head));
		memset(trie,0,sizeof(trie));tot=0;
		memset(d,0,sizeof(d));
		for(i=1;i<n;++i){
			int u,v,w;
			u=in;v=in;w=in;
			u++;v++;
			add(u,v,w);add(v,u,w);
		}
		dfs(1,0);
		int maxn=-1;
		for(i=1;i<=n;++i){
			maxn=max(maxn,query(d[i]));
			insert(d[i]);
		}
		printf("%d\n",maxn);
	}

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值