【题目链接】
【思路要点】
- 考虑若不存在“x”,那么剩余的问题就是一个2-SAT的基本问题。
- 不妨令字符串中仅包含c,显然其他的问题是对称的。
- 限制(x,A,y,A):连接(x,A)->(y,A),(y,B)->(x,B)。
- 限制(x,A,y,B):连接(x,A)->(y,B),(y,A)->(x,B)。
- 限制(x,A,y,C):连接(x,A)->(y,A),(x,A)->(y,B),(y,A)->(x,B),(y,B)->(x,B)。
- 限制(x,B,y,A):连接(x,B)->(y,A),(y,B)->(x,A)。
- 限制(x,B,y,B):连接(x,B)->(y,B),(y,A)->(x,A)。
- 限制(x,B,y,C):连接(x,B)->(y,A),(x,B)->(y,B),(y,A)->(x,A),(y,B)->(x,A)。
- 对于其余限制,由于C不会被取到,所以不用考虑。
- 考虑存在“x”的情况,注意到“x”的数量很少,我们暴力枚举该位上不会出现的一个字符,再运行上述算法,判断是否有解。
- 一组解中每一位至多出现一个字符,因此我们只要枚举“a”和“b”即可。
- 时间复杂度\(O(2^D*(N+M))\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 150005; 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'; 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(""); } void readchar(char &x) { x = getchar(); while (x != 'A' && x != 'B' && x != 'C') x = getchar(); } int n, m, d; int pos[MAXN], bit[MAXN]; char st[MAXN]; int x[MAXN], y[MAXN]; int p[MAXN], q[MAXN], tot; char tx[MAXN], ty[MAXN]; char tp[MAXN], tq[MAXN]; vector <int> a[MAXN], b[MAXN], c[MAXN]; bool instack[MAXN], valid; int cnt, belong[MAXN]; int Stack[MAXN], top; int timer, dfn[MAXN], low[MAXN]; bool selected[MAXN], disable[MAXN]; void tarjan(int pos) { if (!valid) return; instack[pos] = true; Stack[++top] = pos; dfn[pos] = low[pos] = ++timer; for (unsigned i = 0; i < a[pos].size(); i++) if (dfn[a[pos][i]] == 0) { tarjan(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] = ++cnt; instack[tmp] = false; while (tmp != pos) { tmp = Stack[top--]; belong[tmp] = cnt; if (belong[((tmp - 1) ^ 1) + 1] == cnt) { valid = false; return; } instack[tmp] = false; } } } void addedge(int x, int y, bool xp, bool yp) { if (xp && yp) { a[p[x]].push_back(p[y]); a[q[y]].push_back(q[x]); } if (xp && !yp) { a[p[x]].push_back(q[y]); a[p[y]].push_back(q[x]); } if (!xp && yp) { a[q[x]].push_back(p[y]); a[q[y]].push_back(p[x]); } if (!xp && !yp) { a[q[x]].push_back(q[y]); a[p[y]].push_back(p[x]); } } void dfs(int pos) { if (disable[pos]) return; disable[pos] = true; for (unsigned i = 0; i < b[pos].size(); i++) dfs(b[pos][i]); } int main() { read(n), read(d); scanf("\n%s", st + 1); read(m); for (int i = 1; i <= m; i++) { read(x[i]), readchar(tx[i]); read(y[i]), readchar(ty[i]); } int tcnt = 0; for (int i = 1; i <= n; i++) if (st[i] == 'x') pos[++tcnt] = i; for (int i = 1; i <= d; i++) bit[i] = 1 << (i - 1); int goal = (1 << d) - 1; for (int s = 0; s <= goal; s++) { for (int i = 1; i <= d; i++) { if (bit[i] & s) st[pos[i]] = 'a'; else st[pos[i]] = 'b'; } tot = 0; for (int i = 1; i <= n; i++) { p[i] = ++tot; a[tot].clear(); q[i] = ++tot; a[tot].clear(); if (st[i] == 'a') { tp[i] = 'B'; tq[i] = 'C'; } if (st[i] == 'b') { tp[i] = 'A'; tq[i] = 'C'; } if (st[i] == 'c') { tp[i] = 'A'; tq[i] = 'B'; } } for (int i = 1; i <= m; i++) { if (tx[i] == tp[x[i]]) { if (ty[i] != tq[y[i]]) addedge(x[i], y[i], 1, 1); if (ty[i] != tp[y[i]]) addedge(x[i], y[i], 1, 0); } if (tx[i] == tq[x[i]]) { if (ty[i] != tq[y[i]]) addedge(x[i], y[i], 0, 1); if (ty[i] != tp[y[i]]) addedge(x[i], y[i], 0, 0); } } timer = cnt = top = 0; memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(belong, 0, sizeof(belong)); valid = true; for (int i = 1; i <= tot; i++) if (dfn[i] == 0) tarjan(i); if (!valid) continue; static int pr[MAXN], d[MAXN]; memset(d, 0, sizeof(d)); for (int i = 1; i <= cnt; i++) b[i].clear(); for (int i = 1; i <= n; i++) { pr[belong[p[i]]] = belong[q[i]]; pr[belong[q[i]]] = belong[p[i]]; } for (int i = 1; i <= tot; i++) for (unsigned j = 0; j < a[i].size(); j++) { int x = belong[i], y = belong[a[i][j]]; if (x != y) { d[x]++; b[y].push_back(x); } } memset(selected, false, sizeof(selected)); memset(disable, false, sizeof(disable)); static int qu[MAXN]; int l = 1, r = 0; for (int i = 1; i <= cnt; i++) if (d[i] == 0) qu[++r] = i; while (l <= r) { int tmp = qu[l++]; for (unsigned i = 0; i < b[tmp].size(); i++) if (--d[b[tmp][i]] == 0) qu[++r] = b[tmp][i]; } for (int i = 1; i <= r; i++) { if (!disable[qu[i]]) { selected[qu[i]] = true; dfs(pr[qu[i]]); } } for (int i = 1; i <= n; i++) { if (selected[belong[p[i]]] ^ selected[belong[q[i]]]) { if (selected[belong[p[i]]]) printf("%c", tp[i]); else printf("%c", tq[i]); } else { printf("Error\n"); return 0; } } printf("\n"); return 0; } writeln(-1); return 0; }