Codeforces 1702 (Div.3) E

7月份比较忙,所以更的不多,大概每周0-3更吧,
8月份我还会回来的!

进入正题

题面

有一些多米诺骨牌,每个上面都写着两个数字。
我们要把这些多米诺骨牌分成两组,使得每组骨牌上出现的数字各不相同。
输出“YES”或“NO”。

闯关旅途

Level 1

关于这题大致的方向大家想到了吗?
提示:POJ上有一道题叫做食物链
链接点不开的戳这儿

Level 2

没错,就是——并查集。
那么什么时候合并呢?
提示:有些数是可以分两个的,但是有些必须一起出现,你知道是哪些吗?

Level 3

二分!二分!二分!
呃我好像忘说了一个“图”字……
没错,每次对于骨牌 $ (X, Y) $ 我们连接 $ (X, Y + n) $ 和 $ (X + n, Y) $。

Level Extra

$ \color{white}{哎呀,被发现了呢!} $

$ \color{white}{你有木有按Ctrl+A?} $

$ \color{white}{这题可以用并查集来做,每次合并 (X, Y + n) 和 (X + n, Y),每次遇到 (X, Y) 或 (X + n, Y + n) 就是NO,都没有就是YES。} $

Level Boss

来吧,少年!!!

#include <bits/stdc++.h>
using namespace std;

int dsu[400005];
int degree[200005];

int find_root(int x) {
	if (dsu[x] != -1) {
		return dsu[x] = find_root(dsu[x]);
	}
	return x;
}

bool unite(int x, int y) {
	int x_root = find_root(x);
	int y_root = find_root(y);
	if (x_root == y_root) {
		return false;
	}
	dsu[x_root] = y_root;
	return true;
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		memset(dsu, -1, sizeof(dsu));
		memset(degree, 0, sizeof(degree));
		int n;
		scanf("%d", &n);
		for (int i = 0; i < n; i++) {
			int x, y;
			scanf("%d %d", &x, &y);
			x--;
			y--;
			unite(x, y + n);
			unite(x + n, y);
			degree[x]++;
			degree[y]++;
		}
		bool ok = true;
		for (int i = 0; i < n; i++) {
			if (degree[i] > 2) {
				ok = false;
				break;
			}
			if (find_root(i) == find_root(i + n)) {
				ok = false;
				break;
			}
		}
		if (ok == true) {
			puts("Yes");
		} else {
			puts("No");
		}
	}
	return 0;
}

经过了几道题的磨练,你的EXP水涨船高,一路升到了Lv.14 2000。
骚年,敢挑战Codeforces Round 807了吗!

posted @ 2022-07-15 21:15  A-Problem-Solver  阅读(48)  评论(0编辑  收藏  举报