这题还是比较厉害的。题目
首先这是一颗无根树,不会处理,看了书才知道,我们可以转化为有根树,然后根据树的特性和前缀和的性质,可以得到d[x]=d[fa] xor weight(x,d[fa])。由此我们可以dfs出所有点的d,对于任意两点的路径异或,就是d[x] xor d[y],这个是因为异或的性质得到的,用手画两条路径就明白了,就可以转化为序列中任意两个数异或最大值了。(树转序列好像也是一个方向)
当然这题有点卡空间,当list空间过不去,可以用链式前向星,我觉得trie的题都比较耗空间,要建树和图都用前向星吧。
#include<cstdio>
#include<algorithm>
#include<list>
#include<cstring>
#include<iostream>
#include<bitset>
#define int long long
using namespace std;
int trie[100002*33][2],n,u,v,d[100002],ans,k,head[100002],e[100002*2],len[100002*2],nxt[100002*2],num;
bool vis[100002];
void add(int uu,int vv,int ww)
{
e[++num]=vv;
len[num]=ww;
nxt[num]=head[uu];
head[uu]=num;
}
void dfs(int rt)
{
vis[rt]=true;
for(int i=head[rt];i;i=nxt[i])
{
int to=e[i],wei=len[i];
if(!vis[to])
{
d[to]=d[rt]^wei;
dfs(to);
}
}
}
void inse(int x)
{
int p=0;
for(int i=31;i>=0;i--)
{
int c=(x>>i)&1;
if(!trie[p][c])
{
trie[p][c]=k++;
}
p=trie[p][c];
}
}
int fin(int x)
{
int p=0,anss=0;
for(int i=31;i>=0;i--)
{
int c=(x>>i)&1;
int o=c^1;
if(trie[p][o])
{
p=trie[p][o];
anss=anss<<1|1;
}
else
{
p=trie[p][c];
anss=anss<<1;
}
}
return anss;
}
signed main()
{
while(scanf("%lld",&n)!=EOF)
{
num=0;
k=1;
ans=0;
memset(trie,0,sizeof(trie));
memset(vis,false,sizeof(vis));
memset(d,0,sizeof(d));
memset(head,0,sizeof(head));
memset(nxt,0,sizeof(nxt));
//memset(v,0,sizeof(v));
for(int i=1;i<=n-1;i++)
{
int u,v,w;
scanf("%lld %lld %lld",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dfs(1);
for(int i=0;i<n;i++)
{
ans=max(ans,fin(d[i]));
inse(d[i]);
}
/*for(int i=0;i<n;i++)
{
printf("%d ",d[i]);
}
printf("\n");*/
cout<<ans<<endl;
}
}