# 题意
给定一个n个节点的树,树上的边都具有权值,从树中任意选两个点,求两点上的路径值异或起来的最大值
# 题解
数组D[x]表示根节点到x的路径上所有的边权的xor值,并且结构是树,通过dfs求出所有节点的d
求出所有的D数组,那么x节点到y节点上所有的异或权值就是D[x] xor D[y],如果从根分叉的话没有疑问
如果一个节点是另一个节点的祖先节点节点,根据异或性质就可以把从根到祖先节点公共路径抵消
原问题就转换成为D[1]~D[n]中选择任意两个数,求最大的异或值.
1 #include<bits/stdc++.h>
2 using namespace std;
3 const int N=1e5+10;
4 int n;
5 int h[N],e[N*2],ne[N*2],w[N*2],idx;
6 int d[N];
7 int trie[N*31][2],tot=1;
8 inline void add(int x,int y,int z){
9 e[idx]=y;
10 w[idx]=z;
11 ne[idx]=h[x];
12 h[x]=idx++;
13 }
14 inline int dfs(int u,int f,int sum){
15 d[u]=sum;
16 for(int i=h[u];i!=-1;i=ne[i]){
17 int j=e[i];
18 if(j!=f) dfs(j,u,sum^w[i]);
19 }
20 }
21 inline void insert(int x){
22 int p=1;
23 for(int j=30;j>=0;j--){
24 int ch=(x>>j)&1;
25 if(!trie[p][ch])
26 trie[p][ch]=++tot;
27 p=trie[p][ch];
28 }
29 }
30 inline int search(int x){
31 int res=0;
32 int p=1;
33 for(int i=30;i>=0;i--){
34 int ch=x>>i&1;
35 if(trie[p][!ch]) {
36 res += 1 << i;
37 p=trie[p][!ch];
38 }
39 else
40 p=trie[p][ch];
41 }
42 return res;
43 }
44 int main(){
45 ios::sync_with_stdio(0);
46 cin.tie(0);
47 cout.tie(0);
48 memset(h,-1,sizeof h);
49 cin>>n;
50 for(int i=0;i<n;i++){
51 int u,v,w;
52 cin>>u>>v>>w;
53 add(u,v,w);
54 add(v,u,w);
55 }
56 dfs(0,-1,0);
57 int ans=0;
58 for(int i=0;i<n;i++)
59 {
60 insert(d[i]);
61 ans=max(ans,search(d[i]));
62 }
63 cout<<ans;
64 }
来源:https://www.cnblogs.com/hhyx/p/12556501.html