P4551 最长异或路径

P4551 最长异或路径

传送锚点

异或的性质:

  • 一个数异或它本身的值为 \(0\)
  • 任何数异或 \(0\) 的值为原数的值

思路:

  • 利用这一性质, 我们可以把路径的异或和转化为路径两端点到跟的异或和的异或
  • 于是,我们利用 \(01\)Trie , 把原数上每一个数到根的异或和都建一棵 Trie
  • 这样, 问题就转化为了在这新数中寻找最大异或对
  • 跑一边 \(01\)Trie 即可

Code:

/*************************************************************************
    > File Name: p4551.cpp
    > Author: Typedef 
    > Mail: 1815979752@qq.com 
    > Created Time: 2021年07月22日 星期四 21时56分26秒
    > Blog: https://www.cnblogs.com/Illyasviel
 ************************************************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+7;
struct Trie{
	int s[2];
}tr[N*43];
int n;
int sum[N];
int h[N],e[N<<1],ne[N<<1];
template<class T>void qread(T &x){
	x=0;bool f=0;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	if(f) x=-x;
}
int idx=0;
int val[N<<1];
void add(int a,int b,int c){
	e[idx]=b;
	val[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
void dfs(int u,int father){
	for(int i=h[u];~i;i=ne[i]){
		int v=e[i];
		if(v==father) continue;
		sum[v]=sum[u]^val[i];
		dfs(v,u);
	}
}
int cnt=0;
void insert(int val,int pos){
	for(int i=(1<<30);i;i>>=1){
		bool p=val&i;
		if(!tr[pos].s[p]) tr[pos].s[p]=++cnt;
		pos=tr[pos].s[p];
	}
}
int query(int val,int pos){
	int res=0;
	for(int i=(1<<30);i;i>>=1){
		bool p=val&i;
		if(tr[pos].s[p^1]) res+=i,pos=tr[pos].s[p^1];
		else pos=tr[pos].s[p];
	}
	return res;
}
int main(){
	memset(h,-1,sizeof(h));
	qread(n);
	for(int i=1;i<n;i++){
		int x,y,z;
		qread(x),qread(y),qread(z);
		add(x,y,z);
		add(y,x,z);
	}
	dfs(1,-1);
	int ans=0;
	for(int i=1;i<=n;i++)
		insert(sum[i],0);
	for(int i=1;i<=n;i++) ans=max(ans,query(sum[i],0));
	printf("%d\n",ans);
	return 0;
}
posted @ 2021-07-22 22:28  actypedef  阅读(55)  评论(0编辑  收藏  举报