[AGC052B] Tree Edges XOR 题解
[AGC052B] Tree Edges XOR
蛮好的题目。
题意
给你一棵树,和每条边的初始权值与目标权值,每次操作可以将一条边相连的两点所连接的其他边全部异或上这条边的边权,请问最后能否使每条边变成目标权值。
思路
首先考虑性质。我们发现每次操作都涉及很多边的变化,很麻烦,考虑去找不变的量。我们发现,如果考虑一条路径上的权值异或和,每次对一条边操作后,只会改变以这条边所连的两个点之一为一个起点,并且不包含这条边的路径的权值异或和。我们可以考虑以任一点为根,把一个点到根的路径上的权值和设为点权,这样每次操作,相当于是去交换这条边所连接的两点的点权。但是这样做有个问题,根节点如果交换会乱套,我们只需要把根节点连接上一个虚点,把连接的边权变成
但是这样做还没完,因为有一个地方忽略了——根节点(不是虚点!)。我们仅仅只能指定初始树的根节点点权为
最后,我们把求出的目标点权都异或上这个
代码:
#include<bits/stdc++.h> using namespace std; const int N = 1e5+100; inline int read(){ int x = 0; char ch = getchar(); while(ch<'0' || ch>'9') ch = getchar(); while(ch>='0'&&ch<='9') x = x*10+ch-48, ch = getchar(); return x; } struct node{ int nxt, to, wa, wb; }edge[N<<1]; int head[N], tot; void add(int u, int v, int wa, int wb){ edge[++tot].nxt = head[u]; edge[tot].to = v; edge[tot].wa = wa; edge[tot].wb = wb; head[u] = tot; } int w1[N], w2[N]; int rootval; void dfs(int u, int fath){ for(int i = head[u]; i; i = edge[i].nxt){ int v = edge[i].to; if(v == fath) continue; w1[v] = w1[u]^edge[i].wa; w2[v] = w2[u]^edge[i].wb; dfs(v, u); } } int n; int main(){ n = read(); for(int i = 1; i<n; ++i){ int u = read(), v = read(), wa = read(), wb = read(); add(u, v, wa, wb); add(v, u, wa, wb); } dfs(1, 0); for(int i = 1; i<=n; ++i){ rootval^=(w1[i]^w2[i]); } for(int i = 1; i<=n; ++i){ w2[i]^=rootval; } int tmp = 0; sort(w1+1, w1+1+n); sort(w2+1, w2+1+n); for(int i = 1; i<=n; ++i){ if(w1[i] != w2[i]) { puts("NO"); return 0; } } puts("YES"); return 0; }