最长异或路径值

# 题意
给定一个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 }

 

猜你喜欢

转载自www.cnblogs.com/hhyx/p/12556501.html