洛谷 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 int trie[32*maxx][2],cnt; 
12 int val[32*maxx];
13 void add(int u,int v,int w)
14 {
15     e[++tot].to=v,e[tot].val=w;
16     e[tot].next=head[u],head[u]=tot;
17 }
18 void dfs(int u,int fa) //预处理1到各点路径上的异或和
19 {
20     for(int i=head[u];i;i=e[i].next){
21         int v=e[i].to;
22         if(v==fa)continue;
23         dis[v]=dis[u]^e[i].val; 
24         dfs(v,u);
25     }
26 }
27 void Insert(int x)
28 {
29     int rt=0;
30     for(int i=31;i>=0;i--){
31         int id=(x>>i)&1;
32         if(!trie[rt][id])trie[rt][id]=++cnt;
33         rt=trie[rt][id];
34     }
35     val[rt]=x;
36 }
37 int Search(int x)
38 {
39     int rt=0;
40     for(int i=31;i>=0;i--){
41         int id=(x>>i)&1;
42         if(trie[rt][id^1])rt=trie[rt][id^1];
43         else rt=trie[rt][id];
44     }
45     return val[rt];
46 }
47 int main()
48 {
49     int n,u,v,w;
50     scanf("%d",&n);
51     for(int i=1;i<n;i++){
52         scanf("%d%d%d",&u,&v,&w);
53         add(u,v,w);add(v,u,w);
54     }
55     dfs(1,0);
56     for(int i=1;i<=n;i++)Insert(dis[i]);
57     int ans=0;
58     for(int i=1;i<=n;i++) ans=max(ans, dis[i]^Search(dis[i]) );
59     printf("%d\n",ans);
60 }

猜你喜欢

转载自www.cnblogs.com/pangbi/p/12403921.html