「题解」AGC052B Tree Edges XOR

「题解」AGC052B Tree Edges XOR

考虑边权转点权,让边权满足其为相邻点权的异或和,操作变成交换两个点的点权。

随便钦定一个为根,设 di 为初始时 i 的点权,fii 期望得到为多少。如果存在 d,f,满足它们是相同的集合,就有解。

注意到如果确定了一个点的点权,那么其他所有点权都能唯一的确定。

现在钦定 fii 到根路径上的边权和(或者说钦定 f1=0),注意到任何一组解都能把所有点权异或 f1,得到 f1=0 的解,所以判断是否有解就判断 f1=0 的时候是否有解。

现在 f 确定了,看是否存在 d,满足 df 是相同的集合。

现在继续钦定 dii 到根路径上边权和,与 f 相同,所有可能为答案的 d 都是 d 异或上一个 x 得到的。

那么有解的必要条件就是 (d1x)(d2x)...(dnx)=f1f2...fn,由于 n 为奇数,所以可以解出 x 是多少。

由于这仅是必要条件,那么最后还要 check 一下是否合法。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#define pb emplace_back
#define mp std::make_pair
#define fi first
#define se second
typedef long long ll;
typedef std::pair<int, int> pii;
typedef std::pair<ll, int> pli;
typedef std::pair<ll, ll> pll;
typedef std::vector<int> vi;
typedef std::vector<ll> vll;
const ll mod = 998244353;
ll Add(ll x, ll y) { return (x+y>=mod) ? (x+y-mod) : (x+y); }
ll Mul(ll x, ll y) { return x * y % mod; }
ll Mod(ll x) { return x < 0 ? (x + mod) : (x >= mod ? (x-mod) : x); }
ll cadd(ll &x, ll y) { return x = (x+y>=mod) ? (x+y-mod) : (x+y); }
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T>
T &read(T &r) {
	r = 0; bool w = 0; char ch = getchar();
	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
	return r = w ? -r : r;
}
const int N = 100010;
int n, ent, head[N];
int d[N], f[N];
struct Edge {
	int next, to, v1, v2;
}e[N << 1];
inline void add(int x, int y, int w1, int w2) {
	e[++ent].to = y; e[ent].next = head[x]; e[ent].v1 = w1; e[ent].v2 = w2; head[x] = ent;
}
void dfs(int x, int fa, int h1, int h2) {
	d[x] = h1; f[x] = h2;
	for(int i = head[x]; i; i = e[i].next) {
		int v = e[i].to; if(v == fa) continue ;
		dfs(v, x, h1 ^ e[i].v1, h2 ^ e[i].v2);
	}
}
signed main() {
	read(n);
	for(int i = 1; i < n; ++i) {
		int u, v, w1, w2; read(u); read(v); read(w1); read(w2);
		add(u, v, w1, w2);
		add(v, u, w1, w2);
	}
	dfs(1, 0, 0, 0);
	int x = 0;
	for(int i = 1; i <= n; ++i) x ^= f[i] ^ d[i];
	for(int i = 1; i <= n; ++i) d[i] ^= x;
	std::sort(d + 1, d + n + 1);
	std::sort(f + 1, f + n + 1);
	for(int i = 1; i <= n; ++i)
		if(f[i] != d[i]) {
			puts("NO");
			return 0;
		}
	puts("YES");
	return 0;
}
posted @   do_while_true  阅读(65)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
历史上的今天:
2020-10-12 Luogu P6649 「SWTR-05」Grid

This blog has running: 1845 days 1 hours 33 minutes 34 seconds

点击右上角即可分享
微信分享提示