题意:有一个n个节点的树,每条边都有一个权值,一条路径的权值等于指此条路径上所有边权值的异或值。问此棵树权值最大的路径的权值是多少;
解法:先算出每个点到0节点的路径的权值,(dfs一遍即可,由于n最大是5个0,所以要邻接表建图进行dfs)。以后每两个节点之间的路径权值就等于分别与0节点之间权值的异或值(用到一个公式:a^b=(a^c)^(b^c)).所以以后两两比较即可,但是n^2肯定不行,这时就可以用到trie树了。将每个节点的ans[i] (i节点与0节点之间的路径权值) 插入trie树,然后再将每个ans[i]访问并返回最大值,访问时贪心往从高位向低位遍历,每位尽量向反方向走(能保证异或值的最大化)。每次的返回值松弛答案,注意每个ans[i]也要将答案松弛一番,因为答案也有可能是i节点与0节点之间的路径。
代码:
/****************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
using namespace std;
#define eps 1e-8
typedef long long LL;
struct edge
{
int v;
int next;
int num;
} edges[200100];
int n;
int ans[100100];
int count1=0;
int head[100100];
bool rem[100100];
void addedge(int u,int v,int num)
{
edges[count1].v=v;
edges[count1].num=num;
edges[count1].next=head[u];
head[u]=count1++;
}
int count2=1;
struct point
{
int num[2];
} points[3000100];
int getans(int k,int p)
{
int ans=0;
for(int i=30;i>=0;i--)
{
if((1<<i)&k)
{
if(points[p].num[0])
ans+=1<<i,p=points[p].num[0];
else
p=points[p].num[1];
}
else
{
if(points[p].num[1])
ans+=1<<i,p=points[p].num[1];
else
p=points[p].num[0];
}
}
return ans;
}
void insert(int k,int p)
{
for(int i=30;i>=0;i--)
{
if(k&(1<<i))
{
if(points[p].num[1])
p=points[p].num[1];
else
points[p].num[1]=count2++,p=count2-1;
}
else
{
if(points[p].num[0])
p=points[p].num[0];
else
points[p].num[0]=count2++,p=count2-1;
}
}
}
void dfs(int k)
{
if(rem[k]) return ;
rem[k]=1;
for(int i=head[k];i!=-1;i=edges[i].next)
{
int t=edges[i].v;
ans[t]=ans[k]^edges[i].num;
dfs(t);
}
}
void inite()
{
memset(head,-1,sizeof head);
memset(rem,0,sizeof rem);
memset(edges,0,sizeof edges);
memset(points,0,sizeof points);
memset(ans,0,sizeof ans);
count1=0;
count2=1;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
inite();
for(int i=1;i<n;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
}
dfs(0);
for(int i=1;i<n;i++)
insert(ans[i],0);
int ans1=0;
for(int i=1;i<n;i++)
ans1=max(ans1,getans(ans[i],0)),ans1=max(ans1,ans[i]);
cout<<ans1<<'\n';
}
return 0;
}