POJ 3764 DFS+trie树

题意:
给你一棵树,求树中最长的xor路径。(n<=100000)
思路:
首先我们知道 A xor B =(A xor C) xor (B xor C)
我们可以随便选一个点DFS 顺便做出与这个点连接的其它点的xor长度
但是
枚举起点&重点+判断会TLE
所以呢 随后 就是重头戏了:trie树
这是一棵神奇的树 (莫名想到了“这是一个神奇的网站”)

我们可以从高位往低位插这个点的xor的值。(数字前面可以补零)
之后是查找 由于异或的性质,我们可以得到:当此位数字不相同时 xor得到的值最大,那不就好说了嘛。
每回寻找树上有没有与这一位不相同的值的节点
1.若有,w|=(1 << i) 。按此方向向下寻找
2.若没有,继续顺着trie树往下走

注意是多case。
注意清空数组,ans、归零什么的
PoPoQQQ大爷在这里都有惨痛的经历。
《POJ 3764 DFS+trie树》

// by SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 305000
using namespace std;
int first[N],next[N],v[N],w[N],W[N],trie[N*10][2];
int xx,yy,zz,n,tot,cnt,ans;
bool vis[N];
void add(int x,int y,int z){
 v[tot]=y,w[tot]=z;
 next[tot]=first[x],first[x]=tot++;
}
void dfs(int x){
 for(int i=first[x];~i;i=next[i])
 if(!vis[v[i]]){
 vis[v[i]]=1;
 W[v[i]]=W[x]xor w[i];
 dfs(v[i]);
 }
}
void insert(int x){
 int jy=0;
 for(int i=30;i>=0;i--){
 int temp=x&(1<<i)?1:0;
 if(trie[jy][temp]==0)
 trie[jy][temp]=++cnt;
 jy=trie[jy][temp];
 }
}
int find(int x){
 int jy=0,w=0;
 for(int i=30;i>=0;i--){
 int temp=x&(1<<i)?1:0;
 if(trie[jy][!temp])
 w|=(1<<i),jy=trie[jy][!temp];
 else jy=trie[jy][temp];
 }
 return w;
}
int main(){
 while(~scanf("%d",&n)){
 memset(first,-1,sizeof(first));
 memset(trie,0,sizeof(trie));
 memset(vis,0,sizeof(vis));
 memset(W,0,sizeof(W));
 ans=tot=cnt=0;
 for(int i=1;i<n;i++){
 scanf("%d%d%d",&xx,&yy,&zz);
 add(xx,yy,zz),add(yy,xx,zz);
 }
 dfs(xx);
 for(int i=0;i<n;i++)insert(W[i]),ans=max(ans,find(W[i]));
 printf("%d\n",ans);
 }
}

《POJ 3764 DFS+trie树》
万朵红中一点蓝。

    原文作者:Trie树
    原文地址: https://blog.csdn.net/qq_31785871/article/details/51935406
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞