# 题意
给定一个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
时间: 2024-10-13 11:44:06