洛谷 4551 01字典树

题意:给出一颗n个节点的数,节点之间的边有权值,求任意两个节点之间的最大异或值

 

思路:我们将整个图走一遍dfs,求出节点1到其他所有节点的异或值,用数组dis来储存

然后接下来求任意两个节点之间的路径异或值,就是dis【x】^dis【y】

所以我们接下来就用每一个点来遍历一次图,枚举更新最大值即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxx = 1e5+10;
 4 struct node
 5 {
 6     int to,val,next;
 7 }e[2*maxx];
 8 int head[maxx],tot;
 9 int dis[maxx];
10 ///最多不超过32*maxx个节点 
11 ///每个点顶多开32个节点,总共1e5个点。
12 ///如果给出的范围是1e18,那就64个节点
13 int trie[32*maxx][2],cnt;
14 int val[32*maxx];
15 void add(int u,int v,int w)
16 {
17     e[++tot].to=v,e[tot].val=w;
18     e[tot].next=head[u],head[u]=tot;
19 }
20 void dfs(int u,int fa) //预处理1到各点路径上的异或和
21 {
22     for(int i=head[u];i;i=e[i].next){
23         int v=e[i].to;
24         if(v==fa) continue;
25         dis[v]=dis[u]^e[i].val;
26         dfs(v,u);
27     }
28 }
29 void Insert(int x)
30 {
31     int rt=0;
32     for(int i=31;i>=0;i--){
33         int id=(x>>i)&1;
34         if(!trie[rt][id])
35             trie[rt][id]=++cnt;
36         rt=trie[rt][id];
37     }
38     val[rt]=x;
39 }
40 int Search(int x)
41 {
42     int rt=0;
43     for(int i=31;i>=0;i--){
44         int id=(x>>i)&1;
45         if(trie[rt][id^1])
46             rt=trie[rt][id^1];
47         else rt=trie[rt][id];
48     }
49     return val[rt];
50 }
51 int main()
52 {
53     int n,u,v,w;
54     scanf("%d",&n);
55     for(int i=1;i<n;i++){
56         scanf("%d%d%d",&u,&v,&w);
57         add(u,v,w);add(v,u,w);
58     }
59     dfs(1,0);
60     for(int i=1;i<=n;i++)
61         Insert(dis[i]);
62     int ans=0;
63     for(int i=1;i<=n;i++) 
64         ans=max(ans, dis[i]^Search(dis[i]) );
65     printf("%d\n",ans);
66 }
View Code

 

posted @ 2020-03-03 18:39  古比  阅读(192)  评论(0编辑  收藏  举报