1. 问题背景与定义
今天想和大家分享一道经典的树形结构题目——"最长异或路径"。这个问题在算法竞赛和面试中经常出现,考察的是对树结构的理解以及位运算的应用能力。
所谓"最长异或路径",指的是在一棵带权树中,找出两个节点之间的路径,使得路径上所有边的权值的异或结果最大。这里的异或(XOR)是按位进行的二进制运算,具有以下特性:
- 交换律:a ^ b = b ^ a
- 结合律:a ^ (b ^ c) = (a ^ b) ^ c
- 自反性:a ^ a = 0
- 恒等性:a ^ 0 = a
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题分析与解法思路
2.1 暴力解法及其局限性
最直观的解法是枚举所有节点对,计算它们之间路径的异或值,然后取最大值。对于n个节点的树,这样的时间复杂度是O(n²),当n较大时(比如n=1e5),这种解法显然不可行。
2.2 关键观察与优化思路
这里有一个重要的性质可以利用:对于树中的任意两个节点u和v,它们之间路径的异或值等于从根节点到u的异或值与从根节点到v的异或值的异或结果。这是因为:
xor(u,v) = xor(root,u) ^ xor(root,v)
基于这个观察,我们可以将问题转化为:在所有节点到根的异或值中,找出两个数,使它们的异或结果最大。
2.3 使用Trie树优化查找
为了高效地找到最大异或对,我们可以使用Trie树(前缀树)来存储所有节点到根的异或值。具体步骤如下:
- 首先进行一次DFS或BFS遍历,计算每个节点到根节点的异或值,记为xor[u]。
- 将这些xor值构建一个二进制Trie树。
- 对于每个xor[u],在Trie树中查找能与之产生最大异或值的数。
3. 详细实现步骤
3.1 数据结构定义
首先定义树的结构和必要的变量:
cpp复制const int MAXN = 1e5 + 5;
const int BIT = 30; // 假设权值在int范围内
struct Edge {
int to, w, next;
} edges[MAXN * 2];
int head[MAXN], xor_sum[MAXN], tot;
3.2 构建树结构
使用链式前向星存储树结构:
cpp复制void add_edge
