洛谷P2040题解:巧用异或性质,轻松解决树路径查询

一、问题理解
题目给出一个具有N个节点的树,每条边都有一个权值。然后给出M个查询,每个查询要求计算两个节点之间路径上所有边权的异或值。
二、算法选择
我们可以利用树的以下特性:
树是连通无向无环图
任意两点之间有且只有一条简单路径
异或操作具有自反性:a ^ a = 0
基于这些特性,我们可以使用深度优先搜索(DFS)预处理每个节点到根节点的异或值,然后对于任意查询(u,v),结果就是xor[u] ^ xor[v]。
三、C++代码实现
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 1e5 + 5;
struct Edge {
int to, w;
};
vector<Edge> tree[MAXN];
int xor_val[MAXN]; // 存储每个节点到根节点的异或值
bool visited[MAXN];
// DFS预处理每个节点到根节点的异或值
void dfs(int u, int current_xor) {
visited[u] = true;
xor_val[u] = current_xor;
for (const Edge& e : tree[u]) {
if (!visited[e.to]) {
dfs(e.to, current_xor ^ e.w);
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
// 读取树结构
for (int i = 1; i < N; ++i) {
int u, v, w;
cin >> u >> v >> w;
tree[u].push_back({v, w});
tree[v].push_back({u, w});
}
// 预处理异或值
dfs(1, 0); // 假设1是根节点
int M;
cin >> M;
// 处理查询
while (M--) {
int u, v;
cin >> u >> v;
cout << (xor_val[u] ^ xor_val[v]) << '\n';
}
return 0;
}四、代码解析
查询处理:对于查询(u,v),直接输出
xor_val[u] ^ xor_val[v]即可。
五、学习要点
树的DFS遍历应用
异或运算的特殊性质
预处理思想在算法中的应用
如何将路径查询转化为节点到根节点的查询
六、常见问题解答
Q: 为什么选择DFS而不是BFS?A: 两者都可以,DFS实现更简洁,递归形式更容易理解。
Q: 如果树很大怎么办?A: 算法复杂度已经是线性的,对于更大的树可以考虑更高效的IO方式。
Q: 为什么不用LCA算法?A: 由于异或的特殊性质,我们不需要显式计算LCA,这使得算法更简单高效。
原创内容 转载请注明出处
