本文搬运自本人初中博客园博客,若图片加载不出来,可到原文查看:https://www.cnblogs.com/zhangtingxi/p/15792154.html

题目链接

题目

给定一棵 nn 个点的带权树,结点下标从 11 开始到 nn。寻找树中找两个结点,求最长的异或路径。

异或路径指的是指两个结点之间唯一路径上的所有边权的异或

思路

预处理每个点到根节点路劲的异或和,建一棵01trie树。

对于每个节点,在trie树上找离它最远的节点,最后取个 max\max 值即可。

总结

这道题应该也算两个经典问题的集合吧?

首先求树上两个节点之间路径的异或和,这是一个非常经典的问题,由于重复异或没影响,所以可以用树形dp预处理。

这道题巧妙就巧妙在他运用了Trie树,出现异或,还要求最大,trie树是一种非常常用的方法,遇到这种情况可以往Trie树的方面来想。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Problem: P4551 最长异或路径
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4551
// Memory Limit: 64 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
//#define int long long
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<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M
//#define mo
#define N 100010
struct node
{
int x, y, z, n;
}dx[N*2];
struct Node
{
int s[2];
}d[N*30];
int n, m, i, j, k;
int dp[N], u, v, w, h[N];
int ans, cnt;

void cun(int x, int y, int z)
{
dx[++k].x=x; dx[k].y=y; dx[k].z=z;
dx[k].n=h[x]; h[x]=k;
}

void dfs(int x, int fa)
{
for(int g=h[x]; g; g=dx[g].n)
{
int y=dx[g].y;
if(y==fa) continue;
dp[y]=dp[x]^dx[g].z;
dfs(y, x);
}
}

void trie(int x)
{
int i, j, p=1;
for(i=30; i>=0; --i)
{
j=(x&(1<<i))>0;
if(!d[p].s[j]) d[p].s[j]=++cnt;
p=d[p].s[j];
}
}

int find(int dep, int x, int p)
{
if(dep<0) return 0;
int i=(x&(1<<dep))>0;
return find(dep-1, x, (d[p].s[i^1] ? d[p].s[i^1] : d[p].s[i]) )+(d[p].s[i^1] ? (1<<dep) : 0);
}

signed main()
{
// freopen("tiaoshi.in", "r", stdin);
// freopen("tiaoshi.out", "w", stdout);
n=read();
for(i=1; i<n; ++i)
{
u=read(); v=read();
w=read();
cun(u, v, w);
cun(v, u, w);
}
dfs(1, 0);
for(cnt=i=1; i<=n; ++i) trie(dp[i]);
for(i=1; i<=n; ++i) ans=max(ans, find(30, dp[i], 1));
printf("%d", ans);
return 0;
}