题目描述
因为有你的帮忙,pear传教过程中的询问不需要bx2k来算了。趁这个时间,bx2k开始游历汉中。
汉中人民热爱树,所以他们的城市也是树形的。bx2k在汉中有很多喜欢的地点对(u,v),于是他用步伐测量出了每个地点对的距离。做完这个任务后,他回去告诉了pear。pear表示仅仅是距离太弱了,他觉得bx2k应该把城市对之间所有道路的异或和(如果你不知道异或和是啥,请看提示)求出来。bx2k已经不想再走了,于是他把汉中的地图告诉你,让你来帮他完成任务。
输入输出格式
输入格式
第一行包含两个整数n,m,代表汉中有n个地点,bx2k有m个喜欢的地点对。
接下来n-1行,每行包含3个整数u,v,k,代表地点u到地点v之间有一条长度为k的双向道路。
接下来m行,每行包含两个整数u,v,代表bx2k喜欢的地点对。
输出格式
m行,每i行代表第i个地点对之间所有道路的异或和。
输入输出样例
输入样例
5 5
2 1 25431
3 1 25971
4 3 11525
5 4 9170
4 3
5 3
2 1
3 2
4 1
输出样例
11525
3799
25431
1572
18550
说明
数据规模
对于30%的数据,n,m≤10;
对于70%的数据,n,m≤10^3;
对于90%的数据,除1号点外,每个点i均与floor(i/2)有边。
对于100%的数据,n,m,k≤10^5;u,v≤n。
题解
这道题看起来要求lca,但实际上点u和点v的异或和为根到点u和根到点v的异或和(因为点u和点v的所有公共祖先会异或2次,即它们的异或和为0)
具体参考下面的代码。
#include <iostream> #include <cstdio> #define MAX_N 100000 #define MAX_M 100000 using namespace std; int n, m; struct Edge { int next; int to; int val; }; Edge a[(MAX_N << 1) + 5]; int h[MAX_N + 5]; // edge const int root = 1; struct Tree { int parent; int sum; }; Tree t[MAX_N + 5]; // tree inline void Make_Edge(int idx, int u, int v, int k) { a[idx].to = v; a[idx].val = k; a[idx].next = h[u]; h[u] = idx; return; } void Build_Tree() { int x; int st[MAX_N + 5], lt = 1, rt = 1; st[lt] = root; while(lt <= rt) { x = st[lt++]; for(register int i = h[x]; i; i = a[i].next) { if(a[i].to != t[x].parent) { t[a[i].to].parent = x; t[a[i].to].sum ^= t[x].sum ^ a[i].val; st[++rt] = a[i].to; } } } return; } int main() { scanf("%d%d", &n, &m); int u, v, k; for(register int i = 1; i < n; ++i) { scanf("%d%d%d", &u, &v, &k); Make_Edge(i, u, v, k); Make_Edge(i + n, v, u, k); } Build_Tree(); for(register int i = 1; i <= m; ++i) { scanf("%d%d", &u, &v); printf("%d ", t[u].sum ^ t[v].sum); } return 0; }