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了吗!