Description
不想打了戳链接趴
Solution
我可能不会写2-sat
好像去年那个智障白菜写了个“3-sat”???显然这个是个
NPC
N
P
C
问题 (是个ZZ吧!
于是白菜今年终于知道了用”2-sat”和二的
d
d
次方算,但是居然不会写2-sat输出方案。
就是暴枚然后2-sat,注意一定是要加反边的,算法依赖于对称性。特别的,对于某一个点强制其选一种方案,那么这条边没有反边,但是并不影响对称性的应用。(记住好了,懒得证明了
还有一点就是要注意下限制条件时要特判一下处理。二点就是先把拓补序算出来再处理,其中后面连的边是反边,
u−>v
u
−
>
v
表示不选
u
u
就不选,于是下传不选标记和自己的反标记即可。
我是真的不会2-sat
Source
//2018-4-30
//miaowey
//
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define Set(a, v) memset(a, v, sizeof a)
#define For(i, a, b) for(int i = (a); i <= (int)(b); ++i)
#define N (100000 + 5)
struct Con{
int x, hx, y, hy;
}con[N];
char s[N], sid[4][2];
int n, m, d, type[N], numx[N], dig[N], col[N], line[N];
vector<int> G[N], g[N], scc[N];
int dfn, tp, scc_cnt, pre[N], low[N], st[N], sccno[N];
inline void Add(int u, int hu, int v, int hv){
int ou = 6 - type[u] - hu, ov = 6 - type[v] - hv;
hu = ou < hu, hv = ov < hv;
G[u + hu * n].pb(v + hv * n);
}
#define v G[now][i]
void Dfs(int now){
st[++tp] = now;
pre[now] = low[now] = ++dfn;
For(i, 0, G[now].size() - 1)
if(!pre[v]){
Dfs(v); low[now] = min(low[now], low[v]);
}else if(!sccno[v]) low[now] = min(low[now], pre[v]);
if(pre[now] == low[now]){
++scc_cnt;
while(true){
int u = st[tp--];
sccno[u] = scc_cnt; scc[scc_cnt].pb(u);
if(u == now) break;
}
}
}
#undef v
void Tarjan(){
dfn = scc_cnt = 0; Set(pre, 0); Set(sccno, 0);
For(i, 1, n << 1) if(!pre[i]){
tp = 0; Dfs(i);
}
}
void Put(int now, int nc){
if(col[now]) return;
col[now] = nc;
For(i, 0, scc[now].size() - 1){
int u = scc[now][i];
u = u > n? sccno[u - n]: sccno[u + n];
Put(u, 3 - nc);
}
if(nc == 2){
For(i, 0, g[now].size() - 1) Put(g[now][i], 2);
}
}
bool Check(){
int u, v, hu, hv;
Set(dig, 0); Set(col, 0);
For(i, 1, n << 1) G[i].clear(), g[i].clear(), scc[i].clear();
For(i, 1, m){
u = con[i].x, hu = con[i].hx, v = con[i].y, hv = con[i].hy;
if(u == v){
if(hu == hv || hu == type[u]) continue;
Add(u, hu, u, 6 - type[u] - hu);
continue;
}
if(type[u] == hu) continue;
if(type[v] == hv){
Add(u, hu, u, 6 - type[u] - hu); continue;
}
Add(u, hu, v, hv); Add(v, 6 - type[v] - hv, u, 6 - type[u] - hu);
}
Tarjan();
For(i, 1, n) if(sccno[i] == sccno[n + i]) return false;
For(i, 1, n << 1) For(j, 0, G[i].size() - 1){
u = sccno[i], v = sccno[G[i][j]];
if(u != v){
g[v].pb(u); ++dig[u];
}
}
int qn = 0;
queue<int> q;
For(i, 1, scc_cnt) if(!dig[i]) q.push(i);
while(!q.empty()){
int now = q.front(); q.pop();
line[++qn] = now;
For(i, 0, g[now].size() - 1){
v = g[now][i]; if((--dig[v]) == 0) q.push(v);
}
}
For(i, 1, qn){
int now = line[i];
if(col[now]) continue;
Put(now, 1);
}
For(i, 1, n)
if(col[sccno[i]] == 1) printf("%c", sid[type[i]][0]);
else printf("%c", sid[type[i]][1]);
puts("");
return true;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
#endif
scanf("%d%d%s", &n, &d, s + 1);
d = 0;
For(i, 1, n)
if(s[i] == 'x') type[i] = 0, numx[++d] = i;
else if(s[i] == 'a') type[i] = 1;
else if(s[i] == 'b') type[i] = 2;
else type[i] = 3;
sid[1][0] = 'B'; sid[1][1] = 'C';
sid[2][0] = 'A'; sid[2][1] = 'C';
sid[3][0] = 'A'; sid[3][1] = 'B';
int u, v; char h1[5], h2[5];
scanf("%d", &m);
For(i, 1, m){
scanf("%d%s%d%s", &u, h1, &v, h2);
con[i] = (Con){u, h1[0] - 'A' + 1, v, h2[0] - 'A' + 1};
}
For(i, 0, (1 << d) - 1){
For(j, 0, d - 1) type[numx[j + 1]] = (i & (1 << j))? 1: 2;
if(Check()) return 0;
}
puts("-1");
return 0;
}