给定一棵 nn 个点的带权树,结点下标从 11 开始到 nn。寻找树中找两个结点,求最长的异或路径。

异或路径指的是指两个结点之间唯一路径上的所有边权的异或。

 

处理出每个点的树上异或前缀

 这些异或值按照二进制数插入Trie

经典问题了

 

 

#include <iostream>
#include <cstring> 
using namespace std;
const int N=1e6+10,M=N;
int tot=1,ch[N][2];
int n,nxt[M],go[M],hd[N],w[M],all=1;
int g[N];
 void add_(int x,int y,int z){
 	go[++all]=y; w[all]=z;nxt[all]=hd[x]; hd[x]=all;
 }
 
 void dfs(int x,int fa){
 	
 	for(int i=hd[x];i;i=nxt[i]){
 		int y=go[i],z=w[i]; if(y==fa) continue;
 		g[y]=z^g[x];
 		dfs(y,x);
 	}
 }
 void insert(int num){
 	int u=1,c;
 	
 	for(int i=31;i>=0;i--){
 		c=(num>>i)&1;
 		
 		if(ch[u][c]==0) ch[u][c]=++tot;
 		u=ch[u][c];
 	}
 }
 int find(int num){
 	int u=1,c,t=0;
 	
 	for(int i=31;i>=0;i--){
 		c=(num>>i)&1;
 		if(ch[u][c^1]) u=ch[u][c^1],t=t*2+1;
 		else u=ch[u][c],t*=2;
 	}
 	return t;
 }
 
 
 signed main(){
 	cin>>n;
 	int x,y,z,ans=0;
 	for(int i=1;i<n;i++) 
 		cin>>x>>y>>z,add_(x,y,z),add_(y,x,z);
 	dfs(1,0);
 	
 	for(int i=1;i<=n;i++){
 		ans=max(ans,find(g[i]));
 		insert(g[i]);
 	}
 	cout<<ans;
 }
 
 

 

posted on 2023-03-08 20:20  towboat  阅读(21)  评论(0)    收藏  举报