考虑把有111种车不适合跑这样的条件转化一下
111种不适合跑⟶\longrightarrow⟶222种适合跑,并且只能选一种车去跑
可以看到这就是一个2−SAT2-SAT2−SAT模板了。
考虑一下限制。
对于每场比赛拆成222个点,xxx以及x′x'x′,表示这场比赛使用了哪辆适合的车
若iii图选择hih_ihi,jjj图选择hjh_jhj:
如果hih_ihi不适合在iii用,直接略过。
反之,如果hjh_jhj并不适合在jjj用,那么就让iii向i′i'i′连边,表示这个方案并不可行。
如果都适合则连边i,ji,ji,j,i′,j′i',j'i′,j′。
最后检测iii和i′i'i′是否在一个强联通分量里即可。
但是有一种图满足333种车都可以跑,考虑到这种图非常少(≤8\leq 8≤8 ),暴力枚举它适合哪两辆车即可。判定所有方案是否存在可行解即可。
#include <bits/stdc++.h>
int n,d;
int m;
int Time,top;
char s[201000];
int cn[201000];
int dfn[201000];
int low[201000];
int tck[201000];
int vis[201000];
int pos[10],C;
int scc[201000],c;
int head[201000],tot;
struct qwq{
int p1;
char qwp1[1];
int use1;
int p2;
char qwp2[1];
int use2;
}limit[201000];
struct edge{
int to;
int nxt;
}e[201000];
void add(int x,int y){
e[++tot]={y,head[x]};
head[x]=tot;
}
std::pair<int,int> point(int place,int use){
if(cn[place]==1)
return use==2?std::make_pair(place,place+n):std::make_pair(place+n,place);
else
return use==1?std::make_pair(place,place+n):std::make_pair(place+n,place);
}
void make_edge(){
for(int i=1;i<=m;++i){
if(cn[limit[i].p1]==limit[i].use1)
continue;
std::pair<int,int> fst=point(limit[i].p1,limit[i].use1);
if(cn[limit[i].p2]==limit[i].use2){
add(fst.first,fst.second);
continue;
}
std::pair<int,int> scd=point(limit[i].p2,limit[i].use2);
add(fst.first,scd.first);
add(scd.second,fst.second);
}
}
void tarjan(int x){
dfn[x]=low[x]=++Time;
tck[++top]=x;
vis[x]=1;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(!dfn[y]){
tarjan(y);
low[x]=std::min(low[x],low[y]);
}
else
if(vis[y])
low[x]=std::min(low[x],dfn[y]);
}
if(dfn[x]==low[x]){
++c;
while(tck[top]!=x){
vis[tck[top]]=0;
scc[tck[top]]=c;
--top;
}
vis[tck[top]]=0;
scc[tck[top]]=c;
--top;
}
}
main(){
scanf("%d%d",&n,&d);
scanf("%s",s+1);
scanf("%d",&m);
for(int i=1;i<=m;++i){
scanf("%d%s%d%s",&limit[i].p1,limit[i].qwp1,&limit[i].p2,limit[i].qwp2);
limit[i].use1=limit[i].qwp1[0]-'A'+1;
limit[i].use2=limit[i].qwp2[0]-'A'+1;
}
int len=strlen(s+1);
for(int i=1;i<=len;++i){
if(s[i]=='a')
cn[i]=1;
if(s[i]=='b')
cn[i]=2;
if(s[i]=='c')
cn[i]=3;
if(s[i]=='x')
pos[++C]=i;
}
for(int i=0;i<=(1<<d)-1;++i){
tot=c=Time=top=0;
memset(head,0,sizeof head);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(scc,0,sizeof scc);
memset(tck,0,sizeof tck);
memset(vis,0,sizeof vis);
for(int j=0;j<d;++j)
if(i&(1<<j))
cn[pos[j+1]]=1;
else
cn[pos[j+1]]=2;
make_edge();
for(int j=1;j<=2*n;++j)
if(!dfn[j])
tarjan(j);
int f=0;
for(int j=1;j<=n;++j)
if(scc[j]==scc[j+n])
f=1;
if(!f){
for(int j=1;j<=n;++j){
if(cn[j]==1)
if(scc[j]<scc[j+n])
putchar('B');
else
putchar('C');
if(cn[j]==2)
if(scc[j]<scc[j+n])
putchar('A');
else
putchar('C');
if(cn[j]==3)
if(scc[j]<scc[j+n])
putchar('A');
else
putchar('B');
}
return 0;
}
}
puts("-1");
return 0;
}