题目大意:
在一颗树上,找一条路径使这条路上所有边权xor最大
思路:
我们先把树变成有根树
然后处理出每个人到根的路径上的边权xor值,对于两个点间的路径,只需要对于这两个的点的值xor就好了
因为上边的那一部分异或之后就被消了
这种题我们需要把所有值存到trie树里
查询的时候对于每一位尽量查反的
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 100100 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,fst[MAXN],to[MAXN*2],val[MAXN*2],nxt[MAXN*2],g[MAXN],ans; 21 int tr[MAXN*35][2],sz,cnt; 22 void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,val[cnt]=w,to[cnt]=v;} 23 void build(int x,int fa) 24 { 25 for(int i=fst[x];i;i=nxt[i]) 26 { 27 if(to[i]==fa) continue; 28 g[to[i]]=g[x]^val[i]; 29 build(to[i],x); 30 } 31 } 32 void ins(int x)//插入每个值 33 { 34 int tmp,pos=0; 35 for(int i=31;i>=0;i--)//把x的每一位存到trie树里 36 { 37 tmp=1&(x>>i);//不能1<<31 但是可以>>31 38 if(!tr[pos][tmp]) tr[pos][tmp]=++sz; 39 pos=tr[pos][tmp]; 40 } 41 } 42 int Ask(int x) 43 { 44 int res=0,pos=0,tmp; 45 for(int i=31;i>=0;i--) 46 { 47 tmp=1&(x>>i);//不能1<<31 但是可以>>31 48 res<<=1; 49 if(tr[pos][!tmp]) pos=tr[pos][!tmp],res++;//尽量使每一位都是反的 50 else pos=tr[pos][tmp]; 51 } 52 return res; 53 } 54 int main() 55 { 56 int a,b,c; 57 while(scanf("%d",&n)!=EOF) 58 { 59 memset(fst,0,sizeof(fst)); 60 memset(g,0,sizeof(g)); 61 memset(nxt,0,sizeof(nxt));cnt=0; 62 memset(tr,0,sizeof(tr));sz=ans=0; 63 for(int i=1;i<n;i++) {a=read()+1,b=read()+1,c=read();add(a,b,c);add(b,a,c);} 64 build(1,0);//处理成有根树 65 for(int i=1;i<=n;i++) ins(g[i]); 66 for(int i=1;i<=n;i++) ans=max(ans,Ask(g[i])); 67 printf("%d ",ans); 68 } 69 }