poj3764
题意就是给一棵树,然后让你求最大的路经异或和是多少,一条路径的异或和是该路径上的边对应的边权的异或和。
因为^具有自反性,即a^a=0,所以我们只需要dfs处理出根节点到每个点的路径的异或和dp[i],那么u至v的路径的异或和即等于 dp[u]^dp[v],然后把dp[i]都放入01字典树里,枚举起点i,求与dp[i]异或得到的最大的数,然后取最大值即可。
#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
const int maxn=1e5+10;
struct node
{
int val,cnt,son[2];
void reset()
{
val=cnt=son[0]=son[1]=0;
}
}tree[maxn*32];
struct edge
{
int v,w,nxt;
edge(int v=0,int w=0,int nxt=0)
{
this->v=v;
this->w=w;
this->nxt=nxt;
}
}e[2*maxn];
int dp[maxn],head[maxn],n,cnt;
void myinsert(int x)
{
int r=0,v;
for(int i=31;i>=0;i--)
{
v=(x>>i)&1;
if(!tree[r].son[v])
{
tree[++cnt].reset();
tree[r].son[v]=cnt;
}
if(r!=0)
tree[r].cnt++;
r=tree[r].son[v];
}
tree[r].val=x;
tree[r].cnt++;
}
int query(int x)
{
int r=0,v;
for(int i=31;i>=0;i--)
{
v=(x>>i)&1;
if(tree[r].son[v^1]&&tree[tree[r].son[v^1]].cnt)
r=tree[r].son[v^1];
else
r=tree[r].son[v];
}
return tree[r].val^x;
}
void dfs(int now,int fa)
{
int v,w;
for(int i=head[now];i!=-1;i=e[i].nxt)
{
v=e[i].v;
w=e[i].w;
if(v==fa) continue;
dp[v]=dp[now]^w;
dfs(v,now);
}
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*f;
}
int main()
{
int maxx;
while(scanf("%d",&n)!=EOF)
{
tree[0].reset();
cnt=0;
maxx=0;
for(int i=0;i<n;i++) head[i]=-1;
for(int i=1,cnt=0;i<n;i++)
{
int u,v,w;
u=read();
v=read();
w=read();
e[cnt]=edge(v,w,head[u]);
head[u]=cnt++;
e[cnt]=edge(u,w,head[v]);
head[v]=cnt++;
}
dfs(0,-1);
for(int i=0;i<n;i++)
myinsert(dp[i]);
for(int i=0;i<n;i++)
{
maxx=max(maxx,query(dp[i]));
}
printf("%d\n",maxx);
}
return 0;
}