【图论】【位运算】Bakry and Partitioning—CF1592C

Bakry and Partitioning—CF1592C

这个题不好写,即使看提交也要看好长时间(可能是因为我菜)。

思路

本来写了很长,但后来发现那个方法不太好理解,就改了一部分。

关键地方我写了注释。

C o d e Code Code

#include <bits/stdc++.h>
#define int long long
#define sz(a) ((int)a.size())
#define all(a) a.begin(), a.end()
using namespace std;
using PII = pair<int, int>;
using i128 = __int128;
const int N = 2e5 + 10;

int n, k;
int a[N];
int ed[2 * N], ne[2 * N], he[N], idx;
int xor_all; // n点的异或和
int num; // 树中异或和等于xor_all的块数

void add(int u, int v) {
	ed[idx] = v, ne[idx] = he[u], he[u] = idx ++;
}

int dfs(int u, int last) {
	int xr = a[u];
	for (int i = he[u]; i != -1; i = ne[i]) {
		int j = ed[i];
		if (j != last) {
			xr ^= dfs(j, u);
		}
	}
	if (xr == xor_all) {
		num ++;
		xr = 0;
	}
	return xr;
}

void solve() {
	cin >> n >> k;
	for (int i = 1; i <= n; i ++) {
		he[i] = -1;
	}
	xor_all = 0;
	for (int i = 1; i <= n; i ++) {
		cin >> a[i];
		xor_all ^= a[i];
	}
	for (int i = 1; i <= n - 1; i ++) {
		int u, v; cin >> u >> v;
		add(u, v);
		add(v, u);
	}
	
	if (k == 2) {
		/*
		  只能把树分成两个异或和相等的块,
		  设这两块的异或和都是a,
		  所以xor_all = a ^ a = 0
		 */
		if (xor_all == 0) {
			cout << "YES\n";
		} else {
			cout << "NO\n";
		}
	} else { // k >= 3
		num = 0;
		dfs(1, 0);
		/*
		  因为这颗树所能分成的异或和相等的块数
		  的奇偶性不变(因为可以把任意相邻的3块合并
		  为1块),
		  所以能分成奇数块、偶数块异或和相等的树
		  分别能分成3块、2块异或和相等的块。
		  如果是偶数块(能分成2块),易知xor_all == 0;
		  如果是奇数块(能分成3块),我们只需要判断
		  块数是否 > 1即可(当然xor_all时也可以)。
		 */
		if (num % 2 == 0 && xor_all == 0 ||
			num % 2 != 0 && (num > 1 || xor_all == 0)) {
			cout << "YES\n";
		} else {
			cout << "NO\n";
		}
	}
}

signed main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int T = 1;
	cin >> T; cin.get();
	while (T --) solve();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值