题解:
假的$3-SAT$,真的$2-SAT$。
我们可以枚举所有的$x$都是什么,这样做是$O(n*3^d)$的。
但是考虑到$a$包含了$B$和$C$,$b$包含了$A$和$C$,我们可以不用将$x$改成$c$,改成$a$或$b$就好了。
将每个地图分为两个点。比如当前为$a$,那么我们可以选$B$或选$C$。
然后就是$2-SAT$建图。
当然是根据$m$组限制条件了。
对于一组限制条件$(i,hi,j,hj)$:
(1)若$i$不能取$hi$,直接忽略;
(2)若$j$不能取$hj$,说明$i$取$hi$时直接死,所以$(i,hi)->(i,剩下状态)$;
(3)一般情况,$(i,hi)->(j,hj)$,$(j,剩下情况)->(i,剩下情况)$。
然后跑$2-SAT$就好了。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100050; int n,d,m,a[N],pos[10]; char s0[N],s1[10],s2[10]; struct BAN { int i,hi,j,hj; BAN(){} BAN(int i,int hi,int j,int hj):i(i),hi(hi),j(j),hj(hj){} }b[N]; int hed[N],cnt; struct EG { int to,nxt; }e[N<<3]; void ae(int f,int t) { e[++cnt].to = t; e[cnt].nxt = hed[f]; hed[f] = cnt; } int dep[N],low[N],tim,bel[N],bc; int sta[N],tl; bool vis[N]; void init() { memset(hed,0,sizeof(hed)); memset(dep,0,sizeof(dep)); memset(low,0,sizeof(low)); memset(bel,0,sizeof(bel)); memset(vis,0,sizeof(vis)); cnt = tim = bc = tl = 0; } int gt(int x,int i) { if(a[x]<i)return (x<<1)|(i-1); return (x<<1)|i; } void tarjan(int u) { dep[u]=low[u]=++tim; sta[++tl] = u; vis[u] = 1; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(!dep[to]) { tarjan(to); low[u]=min(low[u],low[to]); }else if(vis[to]) low[u]=min(low[u],dep[to]); } if(dep[u]==low[u]) { bc++; int c = -1; while(c!=u) { c = sta[tl--]; vis[c] = 0; bel[c] = bc; } } } bool check() { for(int i=1;i<=n;i++) if(bel[i<<1]==bel[i<<1|1])return 0; return 1; } void print(int x) { if(bel[x<<1]<bel[x<<1|1]) putchar(a[x]==0?'B':'A'); else putchar(a[x]==2?'B':'C'); } int main() { scanf("%d%d%s%d",&n,&d,s0+1,&m); for(int i=1,j=0;i<=n;i++) if(s0[i]!='x')a[i]=s0[i]-'a'; else pos[j++]=i; for(int x,y,i=1;i<=m;i++) { scanf("%d%s%d%s",&x,s1,&y,s2); b[i]=BAN(x,s1[0]-'A',y,s2[0]-'A'); } for(int i=0;i<(1<<d);i++) { init(); for(int j=0;j<d;j++) a[pos[j]] = ((i>>j)&1); for(int j=1;j<=m;j++) { int x = b[j].i,y = b[j].j,bx = b[j].hi,by = b[j].hj; if(a[x]==bx)continue; if(a[y]==by)ae(gt(x,bx),gt(x,3-bx-a[x])); else ae(gt(x,bx),gt(y,by)),ae(gt(y,3-by-a[y]),gt(x,3-bx-a[x])); } for(int j=2;j<=(n<<1|1);j++) if(!dep[j])tarjan(j); if(check()) { for(int j=1;j<=n;j++) print(j); exit(0); } } printf("-1"); return 0; }