调都没调就 1 A 了,开心.
一些细节:
1. 当 3 个点中强制一个点不选时,又有 $(h_{i},h_{j})$ 这种限制时直接跳过即可.
2. 当有 $(h_{i},h_{j})$ 且 $i$ 这个位置存在,但是 $j$ 不存在的时候显然是不可以选择 $i$ 的,那就直接让 $i$ 连 $i'$ 就行.
3. 2-SAT 的建图始终是有对称性的,即 $a->b$ 就要有 $b'->a'$,这个一定注意.
code:
#include <bits/stdc++.h> #define N 100009 #define ll long long #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) using namespace std; char str[N]; stack<int>sta; int n,D,S,m,edges,scc,tim,tot; int vis[N],mark[N],bu[N],ID[2][N],ge[N][4]; int hd[N],to[N<<1],nex[N<<1],dfn[N],low[N],idx[N]; struct data { int i,hi,j,hj; }h[N]; void add(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void tarjan(int x) { sta.push(x),low[x]=dfn[x]=++tim; for(int i=hd[x];i;i=nex[i]) { int y=to[i]; if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]); else if(!idx[y]) low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]) { ++scc; for(;;) { int u=sta.top(); sta.pop(); idx[u]=scc; if(u==x) break; } } } void clr() { for(int i=1;i<=tot;++i) hd[i]=dfn[i]=low[i]=idx[i]=0; for(int i=0;i<=edges;++i) nex[i]=to[i]=0; } int calc() { int x,y,z; for(int i=1;i<=n;++i) { if(vis[i]) { if(mark[i]==0) str[i]='a'; if(mark[i]==1) str[i]='b'; } if(str[i]=='a') ge[i][1]=0,ge[i][2]=1; if(str[i]=='b') ge[i][0]=0,ge[i][2]=1; if(str[i]=='c') ge[i][0]=0,ge[i][1]=1; } for(int i=1;i<=m;++i) { data e=h[i]; // 反正肯定不会选 if(str[e.i]=='a'+e.hi) continue; // 当前肯定不能选 if(str[e.j]=='a'+e.hj) { add(ID[ge[e.i][e.hi]][e.i],ID[ge[e.i][e.hi]^1][e.i]); continue; } // i->j, j'->i' add(ID[ge[e.i][e.hi]][e.i],ID[ge[e.j][e.hj]][e.j]); add(ID[ge[e.j][e.hj]^1][e.j],ID[ge[e.i][e.hi]^1][e.i]); } for(int i=1;i<=tot;++i) if(!dfn[i]) tarjan(i); int flag=1; for(int i=1;i<=n;++i) if(idx[ID[0][i]]==idx[ID[1][i]]) flag=0; if(flag) { for(int i=1;i<=n;++i) { x=ID[0][i],y=ID[1][i]; if(str[i]=='a') printf("%c",idx[x]<idx[y]?'B':'C'); if(str[i]=='b') printf("%c",idx[x]<idx[y]?'A':'C'); if(str[i]=='c') printf("%c",idx[x]<idx[y]?'A':'B'); } } clr(); return flag; } int main() { // setIO("input"); int x,y,z; char a[2],b[2]; scanf("%d%d%s%d",&n,&x,str+1,&m); for(int i=1;i<=m;++i) { scanf("%d%s%d%s",&h[i].i,a,&h[i].j,b); h[i].hi=a[0]-'A',h[i].hj=b[0]-'A'; } for(int i=1;i<=n;++i) if(str[i]=='x') vis[i]=1,bu[++D]=i; for(int i=1;i<=n;++i) ID[0][i]=++tot; for(int i=1;i<=n;++i) ID[1][i]=++tot; // 0 表示 不选 A // 1 表示 不选 B for(int i=0;i<(1<<D);++i) { for(int j=0;j<D;++j) { if(i&(1<<j)) mark[bu[j+1]]=1; else mark[bu[j+1]]=0; } if(calc()) return 0; } if(!D&&calc()) return 0; printf("-1"); return 0; }