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
",res);
59     }
60     return 0;
61 }
原文地址:https://www.cnblogs.com/WABoss/p/5171265.html