POJ3764 The xor-longest Path(Trie树)
题目给一棵有边权的树,问树上任意两点路径上的边异或值最多是多少。
记录每个点u到根路径的异或值xor[u],那么任意两点u、v路径的异或值就是xor[u]^xor[v]。
于是这个问题就变成了从n个数中任取两个数异或,求最大异或值,这是个经典的问题,用字典树解决。
方法就是所有数的二进制形式构建成一棵01字典树,枚举每个数从字典树中就能找到对应的最大的答案。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define MAXN 110000 6 struct Edge{ 7 int v,w,next; 8 }edge[MAXN<<1]; 9 int NE,head[MAXN]; 10 void addEdge(int u,int v,int w){ 11 edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u]; 12 head[u]=NE++; 13 } 14 int tn,ch[3300000][2]; 15 void insert(int a){ 16 int x=0; 17 for(int i=31; i>=0; --i){ 18 int y=(a>>i)&1; 19 if(ch[x][y]==0) ch[x][y]=++tn; 20 x=ch[x][y]; 21 } 22 } 23 int query(int a){ 24 int x=0,res=0; 25 for(int i=31; i>=0; --i){ 26 int y=((a>>i)&1)^1; 27 if(ch[x][y]) x=ch[x][y],res|=1<<i; 28 else x=ch[x][y^1]; 29 } 30 return res; 31 } 32 int val[MAXN]; 33 void dfs(int u,int w,int fa){ 34 val[u]=w; 35 insert(w); 36 for(int i=head[u]; i!=-1; i=edge[i].next){ 37 int v=edge[i].v; 38 if(v==fa) continue; 39 dfs(v,w^edge[i].w,u); 40 } 41 } 42 int main(){ 43 int n,a,b,c; 44 while(~scanf("%d",&n)){ 45 NE=0; 46 memset(head,-1,sizeof(head)); 47 for(int i=1; i<n; ++i){ 48 scanf("%d%d%d",&a,&b,&c); 49 addEdge(a,b,c); addEdge(b,a,c); 50 } 51 tn=0; 52 memset(ch,0,sizeof(ch)); 53 dfs(0,0,0); 54 int res=0; 55 for(int i=0; i<n; ++i){ 56 res=max(res,query(val[i])); 57 } 58 printf("%d\n",res); 59 } 60 return 0; 61 }