题解:AT_agc052_b [AGC052B] Tree Edges XOR

思路

AT_agc052_b [AGC052B] Tree Edges XOR 题目 Link

文中 \(\oplus\) 表示按位异或。

翻看@Soh_paramEEMS 大神的题解,发现有一个题挺有意思,之前做过但是过了时间有点久,现在来看又有新发现了。

具体地,我在图上(树上)问题 trick提到了点边互化的 trick,这题是一个挺成功的范例。具体来说,我们首先要用惊人的注意力发现一次操作的本质。假设选定边 \((u,v)\),边权是 \(w\),然后规定树上任意两点的距离是它们最短路径上边权的异或和(这是一个弱条件的归约,我们通过距离这一弱条件映射约束更强的问题)。不妨令 \(u\) 到所有点的距离集合为 \(s_u\),那么我们的实质相当于交换了集合 \(s_u,s_v\)

Proof

何以见得?考虑其对树上节点距离的影响。用边 \((u,v)\) 把这棵树劈开两半,我们试找到 \(a,b\)(与 \(u,v\) 两两互不相等),它们的距离会如何改变?

分类讨论,如果 \(a,b\) 在同一半,由于这两个点中没有 \(u,v\),所以它们的距离不会改变。如果 \(a,b\) 不在同一半,又由于这两个点中没有 \(u,v\),所以它们的距离相当于其中有两条边分别 \(\oplus w\),最终相当于没异或。

接下来讨论 \(u,a\)\(v,a\) 的情况。

如果 \(u,a\) 在同一半那么其距离中必然会恰出现一条边 \(\oplus w\)。如果 \(u,a\) 不在同一半那么又由于规定了 \(a\neq v\),所以也恰会出现一条边 \(\oplus w\)

\(v\) 的讨论是同理的。然后我们就发现树上两点距离改变当且仅当其中恰有一个点是 \(u\)\(v\)(如果两个点恰好分别是 \(u,v\),显然距离不变)。根据上面的讨论,这次操作会使得 \(s_u,s_v\) 中所有元素除去边 \((u,v)\) 异或上 \(w\),而 \(s_u\) 中每个元素除去边 \((u,v)\) 异或上 \(w\) 恰可以得到 \(s_v\)\(s_v\) 中每个元素除去边 \((u,v)\) 异或上 \(w\) 也恰可以得到 \(s_u\)(这个也可以通过分类讨论简要证明),所以交换集合的结论成立。

这是一个很牛逼的模型,有了它我们就可以把题目归约成一个等价条件:

\(1\) 为树根,我们把每条边边权下放到其连接的两个点中,深度较大点的点权(边化点)上,然后我们就发现 \(1\) 的点权是 \(0\)。计算 \(1\) 到所有节点的距离 \(dis_i\) 可以通过计算路径点权异或和等效得到,我们交换两个不包含 \(1\) 的节点 \(u,v\) 的距离就相当于交换 \(dis_u,dis_v\)。我们发现我们难以描述对 \((1,u)\) 的操作,那么我们干脆就在 \(1\) 上面再加一个虚拟点,向上连一条虚拟边,这样我们永远都不会对虚拟点进行操作,同时根据原模型这又是正确的。题目有个关键条件\(n\) 是奇数,意味着原来有奇数个点,而加入的这个虚拟边权就会在异或中被计算奇数次(也就相当于一次)。于是我们有:

\[x\oplus(\bigoplus_{i=1}^n dis_i)=\bigoplus_{i=1}^n dis'_i \]

右侧 \(dis'_i\) 表示理想状况答案方案希望达到的 \(1\)\(i\) 的距离,这里的 \(x\) 就是 \(1\) 的点权,即 \(1\) 向上连的虚拟边的边权。对于原树,我们虚拟边边权为 \(0\)(因为本来这条边不存在)。对于新树,我们虚拟边边权为 \(x\)

根据异或的互逆性,移项可得:

\[x=(\bigoplus_{i=1}^n dis'_i)\oplus(\bigoplus_{i=1}^n dis_i) \]

然后分别求出 \(dis_i,dis'_i\),判断是否有 \(\forall i,dis_i=dis'_i\) 即可。

总结

我们做了两步关键归约,一是边权化距离(路径异或和)的等效归约,二是边化点与建虚拟边的等效归约。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int n;
struct EV{
	int idx,head[N];
	struct Edge{
		int v,next,w;
	}adj[N<<1];
	void ins(int x,int y,int z){
		adj[++idx].v=y;
		adj[idx].next=head[x];
		adj[idx].w=z;
		head[x]=idx;
	}
}M1,M2;
int a[N],b[N],suma,sumb;
void dfs0(int u,int fa){
	for(int i=M1.head[u];i;i=M1.adj[i].next){
		int v=M1.adj[i].v,w=M1.adj[i].w;
		if(v==fa)continue;
		a[v]=a[u]^w;suma^=a[v];
		dfs0(v,u);
	}
}
void dfs1(int u,int fa){
	for(int i=M2.head[u];i;i=M2.adj[i].next){
		int v=M2.adj[i].v,w=M2.adj[i].w;
		if(v==fa)continue;
		b[v]=b[u]^w;suma^=b[v];
		dfs1(v,u);
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<n;i++){
		int u,v,w1,w2;
		cin>>u>>v>>w1>>w2;
		M1.ins(u,v,w1);M1.ins(v,u,w1);
		M2.ins(u,v,w2);M2.ins(v,u,w2);
	}
	dfs0(1,0);
	dfs1(1,0);
	for(int i=1;i<=n;i++)
		b[i]^=(suma^sumb);
	sort(b+1,b+1+n);
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++)
		if(a[i]!=b[i]){cout<<"NO";return 0;}
	cout<<"YES";
	return 0;
}
posted @ 2025-09-16 19:40  TBSF_0207  阅读(21)  评论(0)    收藏  举报