[UOJ513]UR #19清扫银河

Posted suwakow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[UOJ513]UR #19清扫银河相关的知识,希望对你有一定的参考价值。

非常有意思的一道题,UR 还是一如既往的高水平……就是我比较菜,赛后 15min 突然一拍大腿想出来怎么做了(

首先有一个结论:对于任意图,如果存在方案,一定可以在 (m+1) 步内完成。

证明:首先考虑操作 (2)。先假设所有点都是黑色,逐渐将某些点染白的过程。发现一条边 ((x, y)) 在染白 (x) 时会被翻转,而在染白 (y) 时又会被翻回去。这等价于,将一个点染白时,翻转它所有的连边。因此,每个点最优策略中只会被染白一次,也就是说,(2) 操作只会进行一次,这一次会将所有应该被翻转的点染白。

再考虑操作 (1)。对每个连通块任意构造一棵生成树,则每个非树边唯一对应了一个简单环。不难发现,图中任意一个简单环都可以由上述简单环异或得到(只需要取出这个简单环中,每条非树边对应的环即可)。换句话说,对于任何一种操作 (1) 中选择简单环的方式,都只需要将最终状态中被翻转的非树边对应的环取出来异或。因此操作 (1) 的数量不会超过非树边数量,且一定 (<m)

因此,我们只需要判定给定的图是否存在至少一个方案即可。

假设我们已经选择了 (2^n) 个点集中的一个进行了操作 (2),考虑如何判定是否能通过操作 (1) 变为全 (0)

首先发现若干简单环构成的图,每个点的度数都是偶数。而这恰好是无向图拥有若干不相交欧拉回路的充要条件。又因为每个欧拉回路都能拆成若干简单环,所以一个图由若干简单环构成,等价于它的每个点度数都是偶数。

也就是说我们要求操作 (2) 后,每个点都连接了偶数条不能通行的边。再考虑将一个点染白的影响:任何与它直接连边的点,不能通行的边的奇偶性都会改变。如果这个点本身连边数量为奇数,那么它本身的奇偶性也会改变。也就是说,每个点对应了一个长度为 (n)(01) 向量,现在我们需要选出若干向量,使得他们的异或和等于初始状态下,每个点不能通行的边的奇偶性组成的 (01) 向量。这个问题可以用线性基简单解决,复杂度 (O(frac{n^3}{w}))

Code:

#include <bits/stdc++.h>
#define R register
#define mp make_pair
#define ll long long
#define pii pair<int, int>
using namespace std;
const int mod = 998244353, N = 320;

int t, n, m;
bitset<N> bs[N], to[N], dgr;

inline int addMod(int a, int b) {
	return (a += b) >= mod ? a - mod : a;
}

inline ll quickpow(ll base, ll pw) {
	ll ret = 1;
	while (pw) {
		if (pw & 1) ret = ret * base % mod;
		base = base * base % mod, pw >>= 1;
	}
	return ret;
}

template <class T>
inline void read(T &x) {
	x = 0;
	char ch = getchar(), w = 0;
	while (!isdigit(ch)) w = (ch == ‘-‘), ch = getchar();
	while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
	x = w ? -x : x;
	return;
}

int insrt(bitset<N> &x) {
	for (R int i = n; i; --i) {
		if (!x[i]) continue;
		if (bs[i].none()) return bs[i] = x, 1;
		x ^= bs[i];
	}
	return 0;
}

int main() {
	int x, y, w;
	read(t);
	while (t--) {
		read(n), read(m);
		dgr.reset();
		for (R int i = 1; i <= n; ++i) bs[i].reset(), to[i].reset();
		for (R int i = 1; i <= m; ++i) {
			read(x), read(y), read(w);
			to[x][y] = to[y][x] = 1;
			to[x][x].flip(), to[y][y].flip();
			dgr[x] = dgr[x] ^ w, dgr[y] = dgr[y] ^ w;
		}
		for (R int i = 1; i <= n; ++i) insrt(to[i]);
		printf("%s
", insrt(dgr) ? "no" : "yes");
	}
	return 0;
}

以上是关于[UOJ513]UR #19清扫银河的主要内容,如果未能解决你的问题,请参考以下文章

UR #19

UOJ#22UR#1外星人

UOJ#21UR#1缩进优化

UOJ513 娓呮壂閾舵渤

UOJ83UR #7水题出题人(提交答案题)

UOJ#21UR #1缩进优化