AtCoder Regular Contest 041 D 辺彩色

洛谷传送门

AtCoder 传送门

比较有意思的小清新题。

第一步是时光倒流,看成是每次经过一条未被访问过的边才染色。

奇偶相关容易想到二分图。发现若有一个黑白交替的奇环(即从一个点开始遍历完整个环得到的颜色序列是黑白交替地),那我们可以先染完这个环。又因为它是奇环,所以我们遍历一遍这个环就可以切换颜色。这样一定能把全部边都染上对应的颜色。所以若有一个黑白交替的奇环答案就是 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;
}

posted @ 2024-08-12 22:35  zltzlt  阅读(12)  评论(0编辑  收藏  举报