题意:给出一棵树,每条边有一个权,求出树上一个路径,使得这个路径上所有边的抑或和最大。
题解:以1为根,把每个点到根的抑或和算出来,全插到01字典树,然后再拿着每个点的值去查就行了。复杂度n*32*2。别忘了把根=0插进去。
注意:POJ不给开O2,自己代码里开也没用,STL(vector)会被卡
Code:
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 1e5+100;
int nxt[MAX*32][2];
int first[MAX*2];
int des[MAX*2];
int n[MAX*2];
int len[MAX*2];
int tot,ans,cnt,N;
int bas[40];
void init(){
bas[0] =1;
for (int i=1;i<=30;i++){
bas[i] = bas[i-1]<<1;
}
}
void clear(){
ans = tot= cnt =0;
memset(nxt[0],0,sizeof nxt[0]);
memset(first,0,sizeof first);
}
void add(int x,int y,int z){
tot++;
des[tot] = y;
len[tot] = z;
n[tot] = first[x];
first[x] = tot;
}
void input(){
for (int i=1;i<N;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
u++;v++;
add(u,v,w);
add(v,u,w);
}
}
int create(){
cnt++;
memset(nxt[cnt],0,sizeof nxt[cnt]);
return cnt;
}
void insert(int x){
int nod = 0;
for (int i=30;i>=0;i--){
int t = x&bas[i];
t >>=i;
if (!nxt[nod][t]){
nxt[nod][t] = create();
}
nod = nxt[nod][t];
}
}
void query(int val){
int nod =0;
int res =0;
for (int i=30;i>=0;i--){
int t = val&bas[i];
t>>=i;
if (nxt[nod][!t]){
res+=bas[i];
nod = nxt[nod][!t];
}else{
nod = nxt[nod][t];
}
}
ans = max(ans,res);
}
void dfs(int node,int father,int val){
if (node!=1){
query(val);
}
insert(val);
for (int t = first[node];t;t = n[t]){
if (des[t]==father){
continue;
}
dfs(des[t],node,val^len[t]);
}
}
void solve(){
dfs(1,0,0);
printf("%d\n",ans);
}
int main(){
init();
while (scanf("%d",&N)!=EOF){
clear();
input();
solve();
}
return 0;
}