【题目链接】
【思路要点】
- 需要输出方案的 2 − S A T 2-SAT 2−SAT 问题模板题。
- 时间复杂度 O ( N + M ) O(N+M) O(N+M) 。
【代码】
#include<cstdio> #include<vector> #include<algorithm> #include<cstring> #include<ctype.h> #include<assert.h> using namespace std; const int MAXN = 105; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; if (c == 'h') x = x * 2 - 1; if (c == 'w') x = x * 2 + 0; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, m, p[MAXN]; vector <int> a[MAXN], b[MAXN]; bool instack[MAXN]; int top, Stack[MAXN], tot, belong[MAXN]; int timer, dfn[MAXN], low[MAXN]; void work(int pos) { Stack[++top] = pos; instack[pos] = true; dfn[pos] = low[pos] = ++timer; for (unsigned i = 0; i < a[pos].size(); i++) if (dfn[a[pos][i]] == 0) { work(a[pos][i]); chkmin(low[pos], low[a[pos][i]]); } else if (instack[a[pos][i]]) chkmin(low[pos], dfn[a[pos][i]]); if (dfn[pos] == low[pos]) { int tmp = Stack[top--]; belong[tmp] = ++tot; instack[tmp] = false; while (tmp != pos) { tmp = Stack[top--]; belong[tmp] = tot; instack[tmp] = false; } } } bool ban[MAXN]; void dfs(int pos) { if (ban[pos]) return; ban[pos] = true; for (unsigned i = 0; i < b[pos].size(); i++) dfs(b[pos][i]); } void solve() { timer = tot = 0; memset(dfn, 0, sizeof(dfn)); for (int i = 1; i <= 2 * n; i++) if (dfn[i] == 0) work(i); for (int i = 1; i <= 2 * n; i++) if (belong[i] == belong[p[i]]) { puts("bad luck"); return; } static int d[MAXN], q[MAXN], pr[MAXN]; for (int i = 1; i <= tot; i++) { b[i].clear(); d[i] = 0; } for (int i = 1; i <= 2 * n; i++) pr[belong[i]] = belong[p[i]]; for (int i = 1; i <= 2 * n; i++) for (unsigned j = 0; j < a[i].size(); j++) if (belong[a[i][j]] != belong[i]) { b[belong[a[i][j]]].push_back(belong[i]); d[belong[i]]++; } int l = 1, r = 0; for (int i = 1; i <= 2 * n; i++) if (d[i] == 0) q[++r] = i; while (l <= r) { int tmp = q[l++]; for (unsigned i = 0; i < b[tmp].size(); i++) if (--d[b[tmp][i]] == 0) { q[++r] = b[tmp][i]; } } static bool sel[MAXN]; memset(sel, false, sizeof(sel)); memset(ban, false, sizeof(ban)); for (int i = 1; i <= r; i++) if (!ban[i]) { sel[i] = true; dfs(pr[i]); } for (int i = 1; i <= n; i++) { assert(sel[belong[i * 2 - 1]] ^ sel[belong[i * 2 + 0]]); if (sel[belong[i * 2 - 1]]) printf("%dh ", i); else printf("%dw ", i); } printf("\n"); } int main() { read(n), read(m); while (n != 0 || m != 0) { n--; for (int i = 1; i <= 2 * n; i++) a[i].clear(); for (int i = 1; i <= n; i++) { p[i * 2 - 1] = i * 2 + 0; p[i * 2 + 0] = i * 2 - 1; } for (int i = 1; i <= m; i++) { int x, y; read(x), read(y); if (x == 0 || y == 0) continue; if (x == -1) { a[p[y]].push_back(y); continue; } if (y == -1) { a[p[x]].push_back(x); continue; } a[p[y]].push_back(x); a[p[x]].push_back(y); } solve(); read(n), read(m); } return 0; }