题目链接:(因为bzoj的spj有问题,建议去loj或者洛谷提交)loj链接
首先考虑没有x的情况,因为每张地图都只不适合一辆车参加,反过来说就是只适合两辆车参加。
那么我们完全可以不考虑这两辆车是AB,AC还是BC,都抽象成一辆和另一辆。
对于m组限制条件,如果第i场用u车,那么第j场则必须用j车。
分情况讨论,u表示选第一辆车,u′表示选另一辆车。
1、如果第i张地图本来就不适合u车,说明选u车一定无解,不连任何边。
2、如果第i张地图适合u车,但第j张地图不适合v车,说明第i张地图选u导致第j张地图选v无解,所以第i张地图只能选另一辆车,连边u->u′。
3、如果两张地图都适合,那么连边u->v,由逆否命题对称,再连边v′->u′,表示第j张地图如果选用v′那么第i张地图不能用u,即用u′。
连完边后跑2-sat就好了。
现在考虑有x的情况。
因为x能有三种选择,问题就不是2-sat了。瞅了一眼数据范围:x最多只有8个。那么我们可以2^8暴力枚举x不适合哪辆车,每遍做一次2-sat就行了。
无解情况就是2^8遍跑完后还没有解。
代码:
#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
typedef long long LL;
int read()
{
char c;int sum=0,f=1;c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
return sum*f;
}
char get()
{
char c=getchar();
while(c!='A' && c!='B' && c!='C') c=getchar();
return c;
}
int n,d,m,dep;
char s[maxn],ss[maxn];
int pos[maxn];
int dfn[maxn],low[maxn],bel[maxn];
bool vis[maxn],flag;
stack<int> S;
vector<int> edge[maxn];
int a1[maxn],b1[maxn];
char a2[maxn],b2[maxn];
int num,cur;
void dfs(int x)
{
S.push(x);
dfn[x]=low[x]=++cur;vis[x]=1;
int lens=edge[x].size();
for(int i=0;i<lens;i++)
{
int nex=edge[x][i];
if(!dfn[nex])
{
dfs(nex);
low[x]=min(low[x],low[nex]);
}
else if(vis[nex])
low[x]=min(low[x],dfn[nex]);
}
if(dfn[x]==low[x])
{
int t;
num++;
do
{
t=S.top();S.pop();
vis[t]=0;bel[t]=num;
}
while(t!=x);
}
}
void tarjan()
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));
memset(bel,0,sizeof(bel));
num=cur=0;
for(int i=1;i<=n<<1;i++)
if(!dfn[i]) dfs(i);
}
int cal(int x,char c)
{
if(s[x]=='a') return c=='B'?x:x+n;
if(s[x]=='b' || s[x]=='c') return c=='A'?x:x+n;
if(c=='C') return x+n;
return x;
}
int rev(int x)
{
return x>n?x-n:x+n;
}
void add(int u,int v)
{
edge[u].push_back(v);
}
bool solve()
{
for(int i=1;i<=n<<1;i++)
edge[i].clear();
for(int i=1;i<=m;i++)
{
if(s[a1[i]]!='x' && s[b1[i]]!='x')
{
if(s[a1[i]]-32==a2[i]) continue;
int u=cal(a1[i],a2[i]),v;
if(s[b1[i]]-32==b2[i])
{
add(u,rev(u));
continue;
}
v=cal(b1[i],b2[i]);
add(u,v);add(rev(v),rev(u));
}
else
{
char x=s[a1[i]],y=s[b1[i]];
int u,v,p1=pos[a1[i]],p2=pos[b1[i]];
if(x=='x' && y=='x')
{
if(a2[i]==ss[p1]) continue;
u=cal(a1[i],a2[i]);
if(b2[i]==ss[p2])
{
add(u,rev(u));
continue;
}
v=cal(b1[i],b2[i]);
add(u,v);add(rev(v),rev(u));
}
else if(x!='x' && y=='x')
{
if(s[a1[i]]-32==a2[i]) continue;
u=cal(a1[i],a2[i]);
if(b2[i]==ss[p2])
{
add(u,rev(u));
continue;
}
v=cal(b1[i],b2[i]);
add(u,v);add(rev(v),rev(u));
}
else
{
if(a2[i]==ss[p1]) continue;
u=cal(a1[i],a2[i]);
if(b2[i]==s[b1[i]]-32)
{
add(u,rev(u));
continue;
}
v=cal(b1[i],b2[i]);
add(u,v);add(rev(v),rev(u));
}
}
}
tarjan();
for(int i=1;i<=n;i++)
if(bel[i]==bel[i+n]) return false;
for(int i=1;i<=n;i++)
{
if(bel[i]<bel[i+n])
{
if(s[i]=='a') putchar('B');
else if (s[i]=='b' || s[i]=='C') putchar('A');
else if (ss[pos[i]]=='A') putchar('B');
else putchar('A');
}
else
{
if(s[i]=='a' || s[i]=='b') putchar('C');
else if (s[i]=='c') putchar('B');
else if (ss[pos[i]]== 'A') putchar('C');
else putchar('B');
}
}
return true;
}
void dfs2(int dd)
{
if(dd>dep)
{
if(!flag) flag=solve();
if(flag) exit(0);
return;
}
ss[dd]='A';dfs2(dd+1);
ss[dd]='B';dfs2(dd+1);
}
int main()
{
n=read();d=read();
scanf("%s",s+1);
for(int i=1;i<=n;i++)
{
if(s[i]=='x')
pos[i]=++dep;
}
m=read();
for(int i=1;i<=m;i++)
a1[i]=read(),a2[i]=get(),b1[i]=read(),b2[i]=get();
dfs2(1);
if(!flag)
puts("-1");
return 0;
}