2-SAT。洛谷P3845
一开始以为——怎么有3个呢?后来发现因为每个地图都有一种车是不能用的,所以就等于每一个地图都有两个适应的车啦。
那么对于x类型的地图呢——只有8个,直接2^8暴力枚举每一种可能,就转化为了普通的问题。
令u,u'分别为一个地图适应的两种车,那么对于一个要求h1 - d1, h2 - d2而言,如果第一个既不是u,也不是u’,说明可以无视;如果第二个都不能满足,
就连d1 - d1',表示如果必须选第一辆,问题无解。其余情况则d1-d2,d2'-d1'(重要!保证图的对偶性)
#include <bits/stdc++.h> using namespace std; #define maxn 500050 int n, timer, dep[maxn], m, cnp = 1, d1[maxn], d2[maxn], c1[maxn], c2[maxn], cnt, a[maxn]; int low[maxn], dfn[maxn], num[maxn]; int sum; int head[maxn]; bool flag = false, vis[maxn], mark[maxn]; string s; char tem1[3], tem2[3]; stack <int> st; struct edge { int last, to; }E[maxn]; void add(int u, int v) { E[cnp].to = v, E[cnp].last = head[u]; head[u] = cnp ++; } int getid(int r, int col) { if(a[r] == col) return 0; else if(a[r] == 0) return 2 * r + col - 1; else if(a[r] == 1) return 2 * r + col / 2; else return 2 * r + col; } void tarjan(int u) { dep[u] = dfn[u] = low[u] = ++ timer; vis[u] = mark[u] = true; st.push(u); for(int i = head[u]; i; i = E[i].last) { int v = E[i].to; if(vis[v]) { if(mark[v] && low[u] > dfn[v]) low[u] = dfn[v]; } else { tarjan(v); low[u] = min(low[v], low[u]); } } if(dfn[u] == low[u]) { int j; ++ cnt; do { j = st.top(); st.pop(); num[j] = cnt; mark[j] = false; }while(!st.empty() && j != u); } } void init() { memset(head, 0, sizeof(head)); memset(dep, 0, sizeof(dep)); cnt = timer = 0, cnp = 1; memset(vis, 0, sizeof(vis)); } void solve() { init(); for(int i = 1; i <= m; i ++) { int x = getid(d1[i], c1[i]), y = getid(d2[i], c2[i]); if(x) { if(y) add(x, y), add(y ^ 1, x ^ 1); else add(x, x ^ 1); } } for(int i = 2; i <= 2 * n + 1; i ++) if(!vis[i]) tarjan(i); for(int i = 1; i <= n; i ++) if(num[i * 2] == num[i * 2 ^ 1]) return; flag = true; for(int i = 1; i <= n; i ++) { if(a[i] == 0) putchar(num[i * 2] < num[i * 2 ^ 1] ? 'B' : 'C'); else if(a[i] == 1) putchar(num[i * 2] < num[i * 2 ^ 1] ? 'A' : 'C'); else putchar(num[i * 2] < num[i * 2 ^ 1] ? 'A' : 'B'); } return; } void dfs(int x) { if(flag) return; if(x > n) { solve(); return; } if(a[x] == -1) a[x] = 0, dfs(x + 1), a[x] = 1; dfs(x + 1); } int main() { string s; int d; cin >> n >> d; cin >> s; n = s.length(); for(int i = 0; i < n; i ++) { if(s[i] == 'a') a[i + 1] = 0; else if(s[i] == 'b') a[i + 1] = 1; else if(s[i] == 'c') a[i + 1] = 2; else a[i + 1] = -1; } cin >> m; for(int i = 1; i <= m; i ++) { scanf("%d%s%d%s", &d1[i], tem1, &d2[i], tem2); c1[i] = tem1[0] - 'A', c2[i] = tem2[0] - 'A'; } dfs(1); if(!flag) printf("-1\n"); return 0; }