AtCoder Regular Contest 041 D 辺彩色
比较有意思的小清新题。
第一步是时光倒流,看成是每次经过一条未被访问过的边才染色。
奇偶相关容易想到二分图。发现若有一个黑白交替的奇环(即从一个点开始遍历完整个环得到的颜色序列是黑白交替地),那我们可以先染完这个环。又因为它是奇环,所以我们遍历一遍这个环就可以切换颜色。这样一定能把全部边都染上对应的颜色。所以若有一个黑白交替的奇环答案就是 Yes。
这部分的判定可以先枚举一个点 \(u\) 然后 bfs,设 \(f_{v, 0/1}\) 表示能否经过偶数 / 奇数条黑白交替的边到达点 \(v\)。那么存在一个包含 \(u\) 的黑白交替的奇环等价于存在 \(u\) 的一条出边 \((u, v)\) 使得 \(f_{v, 0} = 1\)。
那么其他情况我们就无法切换颜色,也就是说每次到一个点,它出去时给边染的颜色是固定的。根据这个我们也可以给点染色,一个点的颜色代表它走一步时会给对应的出边染什么颜色。
因为每个点的颜色必须是唯一的,所以此时若图不是二分图就无解。否则我们枚举一个出发点 \(u\) 和 \(u\) 的颜色,判断能不能遍历完整个图(如果一个点的出边和这个点颜色相同就可以继续遍历下去)。如果存在一个点 \(u\) 和 \(u\) 的颜色,使得能遍历完整个图,答案就是 Yes,否则就是 No。
时间复杂度 \(O(nm)\)。
code
// Problem: 🧪
// D - 辺彩色
// Contest: AtCoder - AtCoder Regular Contest 041
// URL: https://atcoder.jp/contests/arc041/tasks/arc041_d
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<int, int> pii;
const int maxn = 2020;
int n, m, f[maxn][2], b[maxn];
vector<pii> G[maxn];
struct node {
int u, v, d;
node(int a = 0, int b = 0, int c = 0) : u(a), v(b), d(c) {}
} a[maxn];
bool dfs(int u) {
for (pii p : G[u]) {
int v = p.fst;
if (b[v] == -1) {
b[v] = b[u] ^ 1;
if (!dfs(v)) {
return 0;
}
} else if (b[u] == b[v]) {
return 0;
}
}
return 1;
}
void dfs2(int u) {
for (pii p : G[u]) {
int v = p.fst, d = p.scd;
if (d == b[u] && b[v] == -1) {
b[v] = b[u] ^ 1;
dfs2(v);
}
}
}
void solve() {
scanf("%d%d", &n, &m);
for (int i = 1, u, v; i <= m; ++i) {
char op[9];
scanf("%d%d%s", &u, &v, op);
int d = (op[0] == 'r');
G[u].pb(v, d);
G[v].pb(u, d);
a[i] = node(u, v, d);
}
for (int i = 1; i <= n; ++i) {
mems(f, 0);
queue<pii> q;
f[i][0] = 1;
q.emplace(i, 0);
while (q.size()) {
int u = q.front().fst, o = q.front().scd;
q.pop();
for (pii p : G[u]) {
int v = p.fst, d = p.scd;
if (o == d && !f[v][o ^ 1]) {
f[v][o ^ 1] = 1;
q.emplace(v, o ^ 1);
}
}
}
for (pii p : G[i]) {
if (f[p.fst][0]) {
puts("Yes");
return;
}
}
}
mems(b, -1);
b[1] = 0;
if (!dfs(1)) {
puts("No");
return;
}
for (int i = 1; i <= n; ++i) {
mems(b, -1);
b[i] = 0;
dfs2(i);
bool fl = 1;
for (int j = 1; j <= n && fl; ++j) {
fl &= (b[j] != -1);
}
if (fl) {
puts("Yes");
return;
}
mems(b, -1);
b[i] = 1;
dfs2(i);
fl = 1;
for (int j = 1; j <= n && fl; ++j) {
fl &= (b[j] != -1);
}
if (fl) {
puts("Yes");
return;
}
}
puts("No");
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}