传送门:uoj317
题解
本蒟蒻也不知道为什么extra test 会WA 5啊,只能在bzoj4945上AC一下以安慰自己。
如果不了解2-SAT,大家可以看一下这份讲解,感觉还是很好懂,后面拓扑排序那里想一下就好了。
2-SAT算法很好理解,但很多人并不知道怎么输出方案,这里贴一篇博客,其中也解释到了排序缩点序和
拓扑序和方案选择之间的关系。
此题特殊在,它的边并不是对称的。
在处理操作时候可以这样:
如
hi
h
i
本身不成立,直接跳过。
若
hi
h
i
可行但
hj
h
j
不可行,就从
i
i
向连一条边,这样保证一旦选取了
i
i
,就不可能成立。若两者都可行,就从向
j
j
连一条边,再从向
i′
i
′
连一条边(反否)。(后者满足对称性质,前者则不满足)。
以上是在不考虑x的情况下。
那么对于x,直接
28
2
8
枚举。为了不TLE,本蒟蒻当然要想方设法降低常数啊,具体看代码。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10;
const int M=1e5+10;
int n,m;
int d,aa[M],bb[M],sta[N<<2],top;
int in[N],head[N<<1],to[M<<2],nxt[M<<2],tot,cir;
int dfn[N<<1],ins[N<<1],low[N<<1],cnt,bel[N<<1];
char s[N],a[M],b[M],ba[20];
bool flag=false,jud;
inline int rd()
{
char ch=getchar();int x=0,f=1;
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
inline char init()
{char ch=getchar();while(ch!='A' && ch!='B' && ch!='C') ch=getchar();return ch;}
inline int get(int x,char c)
{
if(s[x]=='a') return c=='B'? x:x+n;
else if(s[x]!='x') return c=='A'? x:x+n;
else return c=='C'? x+n:x;
}
inline int neg(int x){return x>n? x-n:x+n;}
inline void lk(int u,int v)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
inline void Tarjan(int x)
{
dfn[x]=low[x]=++cnt;sta[++top]=x;ins[x]=1;
for(int i=head[x];i;i=nxt[i]){
if(!dfn[to[i]]){
Tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}else if(ins[to[i]]) low[x]=min(low[x],dfn[to[i]]);
}
if(dfn[x]==low[x])
for(++cir;sta[top+1]!=x;top--) bel[sta[top]]=cir,ins[sta[top]]=0;
if(bel[x]==bel[neg(x)] && bel[x]){
jud=false;return;
}
}
inline bool solve()
{
int i;
cnt=tot=cir=0;int u,v;
for(i=1;i<=(n<<1);i++){head[i]=dfn[i]=bel[i]=ins[i]=0;}
for(i=1;i<=m;i++){
if(s[aa[i]]!='x' && s[bb[i]]!='x'){
if(s[aa[i]]-32 == a[i]) continue;
u=get(aa[i],a[i]);
if(s[bb[i]]-32 == b[i]){lk(u,neg(u));continue;}
v=get(bb[i],b[i]);lk(u,v);lk(neg(v),neg(u));
}else{
if(s[aa[i]]=='x'){
if(ba[in[aa[i]]] == a[i]) continue;
u=get(aa[i],a[i]);
if(s[bb[i]]=='x'){
if(ba[in[bb[i]]] == b[i]){lk(u,neg(u));continue;}
v=get(bb[i],b[i]);lk(u,v);lk(neg(v),neg(u));
}else{
if(s[bb[i]]-32 == b[i]){lk(u,neg(u));continue;}
v=get(bb[i],b[i]);lk(u,v);lk(neg(v),neg(u));
}
}else{
if(s[aa[i]]-32 == a[i]) continue;
u=get(aa[i],a[i]);
if(ba[in[bb[i]]] == b[i]){lk(u,neg(u));continue;}
v=get(bb[i],b[i]);lk(u,v);lk(neg(v),neg(u));
}
}
}jud=true;
for(i=1;i<=(n<<1) && jud;i++) if(!dfn[i]) Tarjan(i);
if(!jud) return false;
for(i=1;i<=n;i++){
if(bel[i]<bel[i+n]){
if(s[i]=='a') putchar('B');
else if(s[i]!='x') putchar('A');
else if(ba[in[i]]=='A') putchar('B');
else putchar('A');
}else{
if(s[i]=='c') putchar('B');
else putchar('C');
}
}
return true;
}
inline void dfs(int depth)
{
if(flag) return;
if(depth==d+1){
if(!flag) flag=solve();
if(flag) exit(0);
return;
}
ba[depth]='A';dfs(depth+1);
ba[depth]='B';dfs(depth+1);
}
int main(){
n=rd();rd();
scanf("%s",s+1);
for(int i=1;i<=n;i++)
if(s[i]=='x') in[i]=++d;
m=rd();
for(int i=1;i<=m;i++){
aa[i]=rd();a[i]=init();
bb[i]=rd();b[i]=init();
}
dfs(1);
if(!flag) printf("-1\n");
return 0;
}