Abstract
傳送門
很有意思的一道題,需要巧妙的利用異或的結合律。
Idea
不妨取 1 為根節點,然後從 1 出發遍歷整棵樹,將 1 到 n 節點的路徑異或和記錄為 dis[i] ,那麼,顯然有從 i 到 j 的路徑的異或和為 dis[i] ^ dis[j]。
Code
愛來自 namespace
#include <bits/stdc++.h>
int n, m;
namespace graph
{
const int maxn = 1100000;
struct Edge
{
int next, to, value;
} edge[maxn];
int head[maxn];
int cnt = 0;
void add(int u, int v, int c)
{
cnt++;
edge[cnt].next = head[u];
edge[cnt].to = v;
edge[cnt].value = c;
head[u] = cnt;
return;
}
int dis[maxn];
bool vis[maxn];
void dfs(int pos, int sum)
{
dis[pos] = sum;
vis[pos] = 1;
for (int i = head[pos]; i; i = edge[i].next)
{
if (vis[edge[i].to])
{
continue;
}
dfs(edge[i].to, sum ^ edge[i].value);
}
return;
}
};
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n;
memset(graph::head, 0, sizeof graph::head);
memset(graph::vis, 0, sizeof graph::vis);
memset(graph::dis, 0, sizeof graph::dis);
for (int i = 1; i < n; i++)
{
int u, v, c;
std::cin >> u >> v >> c;
graph::add(u, v, c);
graph::add(v, u, c);
}
graph::dfs(1, 0);
std::cin >> m;
for (int i = 0; i < m; i++)
{
int x, y;
std::cin >> x >> y;
std::cout << (graph::dis[x] ^ graph::dis[y]) << std::endl;
}
return 0;
}