我是用链式前向星实现的,具体链式前向星是 百度的模板。。。
C++ 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+6;
int a[maxn];
int son[maxn*3][2];
int n;
struct Edge {
int to; //当前节点指向哪个点
int w; //当前权值
int next; //当前节点还有哪些子节点
} edge[maxn * 2];
int head[maxn], idx = 0;
void add_edge(int from, int to, int w) //链式前向星存边
{
edge[++idx].next = head[from]; //head[i],表示以i为起点的第一条边在边集数组的位置(编号)
edge[idx].to = to;
edge[idx].w = w;
head[from] = idx;
}
void insert(int x) //同上题
{
int p = 0;
for(int i = 30; i >= 0; i --)
{
int u = x >> i & 1;
if(!son[p][u]) son[p][u] = ++idx;
p = son[p][u];
}
}
void dfs(int from, int father, int sum) // dfs遍历这个树
{
a[from] = sum; //对于from这个点,目前的值为sum
for(int i = head[from]; i; i = edge[i].next) //遍历这个点的所有子节点
{
if(edge[i].to != father) //如果子节点不是父节点
{
dfs(edge[i].to, from, sum^edge[i].w); //则dfs他,并且存下异或值
}
}
}
int query(int x) //查询同上
{
int p = 0, ans = 0;
for(int i = 30; i >= 0; i --)
{
int num = (x >> i) & 1;
if(son[p][!num])
{
ans += (1 << i);
p = son[p][!num];
}
else p = son[p][num];
}
return ans;
}
int main()
{
memset(head, -1, sizeof(head)); //初始化
scanf("%d",&n);
for(int i = 2; i <= n; i ++)
{
int u, v, w;
scanf("%d%d%d",&u,&v,&w);
add_edge(++u,++v,w); //我也不明白为什么++存! 求助
add_edge(v,u,w);
}
dfs(1, 1, 0); //第一个节点,它来自第一个节点,价值为0
int res = 0; //之后同上题一样
for(int i = 1; i <= n; i ++)
{
insert(a[i]);
}
for(int i = 1; i <= n; i ++)
{
res = max(res, query(a[i]));
}
printf("%d\n",res);
return 0;
}