title
BZOJ 4945
LUOGU 3825
Description
狂野飙车是小 L 最喜欢的游戏。与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略。
小 L 计划进行n场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏。
小 L 的赛车有三辆,分别用大写字母A、B、C表示。地图一共有四种,分别用小写字母x、a、b、c表示。其中,赛车A不适合在地图a上使用,赛车B不适合在地图b上使用,赛车C不适合在地图c上使用,而地图x则适合所有赛车参加。适合所有赛车参加的地图并不多见,最多只会有d张。
n 场游戏的地图可以用一个小写字母组成的字符串描述。例如:S=xaabxcbc表示小 L 计划进行8场游戏,其中第1场和第5场的地图类型是x,适合所有赛车,第2场和第3场的地图是a,不适合赛车A,第4场和第7场的地图是b,不适合赛车B,第6场和第8场的地图是c,不适合赛车C。
小 L 对游戏有一些特殊的要求,这些要求可以用四元组 \((i, h_i, j, h_j)\)来描述,表示若在第\(i\)场使用型号为\(h_i\)的车子,则第\(j\)场游戏要使用型号为\(h_j\)的车子。
你能帮小 L 选择每场游戏使用的赛车吗?如果有多种方案,输出任意一种方案。如果无解,输出 “-1’’(不含双引号)。
Input
输入第一行包含两个非负整数\(n, d\)。
输入第二行为一个字符串\(S\)。\(n, d, S\)的含义见题目描述,其中\(S\)包含\(n\)个字符,且其中恰好\(d\)个为小写字母\(x\)。
输入第三行为一个正整数\(m\),表示有\(m\)条用车规则。接下来\(m\)行,每行包含一个四元组\(i, h_i, j, h_j\),其中\(i, j\)为整数,\(h_i, h_j\)为字符a、b或c,含义见题目描述。
Output
输出一行。
若无解输出 “-1’’(不含双引号)。
若有解,则包含一个长度为n的仅包含大写字母A、B、C的字符串,表示小 L 在这n场游戏中如何安排赛车的使用。如果存在多组解,输出其中任意一组即可。
因为spacial judge,最后一行不要输出回车。
Sample Input
3 1
xcc
1
1 A 2 B
Sample Output
ABA
HINT
【样例1解释】
小 L 计划进行3场游戏,其中第1场的地图类型是x,适合所有赛车,第2场和第3场的地图是c,不适合赛车C。
小 L 希望:若第1场游戏使用赛车A,则第2场游戏使用赛车B。那么为这3场游戏分别安排赛车A、B、A可以满足所有条件。若依次为3场游戏安排赛车为BBB或BAA时,也可以满足所有条件,也被视为正确答案。但依次安排赛车为AAB或ABC时,因为不能满足所有条件,所以不被视为正确答案。
详细信息解释:
1.score:QAQ:此测试点应该输出-1然而你输出的是别的
2.score:QWQ:此测试点应该输出-1然而你输出的是-XXX(就是负号对了后面错了)
3.score:pwp:此测试点应该输出-1并且你的答案是正确的
4.score:qwq:你的方案里出现了不是A,B,C的字符
5.score:qaq:你的方案在第x的图中用了不让用的车
6.score:pvp:你的方案不能满足第x个约束
7.score:qvq:你的答案正确,恭喜嘤嘤嘤
else:蛇皮judge没能正确读入应该读的东西……
analysis
刚看到题目,很像是 \(3-SAT\) 问题,但是 \(d\) 最大只有 \(8\),所以可以 \(3^8\) 枚举禁止选哪种赛车,又发现其实可以枚举禁止 A (可以选B,C)或者禁止 B (可以选A,C),这样的话,所有的情况其实都被讨论过了,复杂度就有了:\(O(2^n)\)。
接下来,容易发现是一个 \(2-SAT\) 问题,跑一个 \(tarjan\) ,缩点建图,然后根据 \(belong[i]\) 的大小选择第一个还是第二个,总复杂度:\(O(2^nn)\)。
code
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
template<typename T>inline void write(T x)
{
if (!x) { putchar('0'); return ; }
if (x<0) putchar('-'), x=-x;
T num=0, ch[20];
while (x) ch[++num]=x%10+48, x/=10;
while (num) putchar(ch[num--]);
}
inline char get()
{
char ch;
while ((ch=getchar())^'A' && ch^'B' && ch^'C');
return ch;
}
int ver[maxn<<1],Next[maxn<<1],head[maxn],len;
inline void add(int x,int y)
{
ver[++len]=y,Next[len]=head[x],head[x]=len;
}
int dfn[maxn],low[maxn],id;
int Stack[maxn],top;
int belong[maxn],tot;
bool instack[maxn];
inline void tarjan(int x)
{
dfn[x]=low[x]=++id;
Stack[++top]=x;
instack[x]=1;
for (int i=head[x]; i; i=Next[i])
{
int y=ver[i];
if (!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if (instack[y])
low[x]=min(low[x],dfn[y]);
}
if (low[x]==dfn[x])
{
int k;
++tot;
do
{
k=Stack[top--];
belong[k]=tot;
instack[k]=0;
} while (k!=x);
}
}
int n,m,tmp;
inline int neg(int x)
{
return x>n?x-n:x+n;
}
char s[maxn];
inline int trans(int x,char ch)
{
if (s[x]=='a') return ch=='B'?x:x+n;
if (s[x]=='b' || s[x]=='c') return ch=='A'?x:x+n;
if (ch=='C') return x+n;
return x;
}
char a2[maxn],b2[maxn],Orz[maxn];
int a1[maxn],b1[maxn],all[maxn];
inline bool solve()
{
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(belong,0,sizeof(belong));
len=id=tot=0;
for (int i=1; i<=m; ++i)
if (s[a1[i]]^'x' && s[b1[i]]^'x')
{
if (a2[i]==s[a1[i]]-32) continue;
int u=trans(a1[i],a2[i]);
if (b2[i]==s[b1[i]]-32) { add(u,neg(u)); continue; }
int v=trans(b1[i],b2[i]);add(u,v);
add(neg(v),neg(u));//反向连边
}
else
{
char o=s[a1[i]],p=s[b1[i]];
int x=all[a1[i]],y=all[b1[i]];
if (o=='x' && p=='x')
{
if (a2[i]==Orz[x]) continue;
int u=trans(a1[i],a2[i]);
if (b2[i]==Orz[y]) { add(u,neg(u)); continue; }
int v=trans(b1[i],b2[i]);add(u,v);
add(neg(v),neg(u));
}
else if (o=='x' && p^'x')
{
if (a2[i]==Orz[x]) continue;
int u=trans(a1[i],a2[i]);
if (b2[i]==s[b1[i]]-32) { add(u,neg(u)); continue; }
int v=trans(b1[i],b2[i]);add(u,v);
add(neg(v),neg(u));
}
else
{
if (a2[i]==s[a1[i]]-32) continue;
int u=trans(a1[i],a2[i]);
if (b2[i]==Orz[y]) { add(u,neg(u)); continue; }
int v=trans(b1[i],b2[i]);add(u,v);
add(neg(v),neg(u));
}
}
for (int i=1; i<=(n<<1); ++i)
if (!dfn[i]) tarjan(i);
for (int i=1; i<=n; ++i)
if (belong[i]==belong[i+n]) return 0;
for (int i=1; i<=n; ++i)
if (belong[i]<belong[i+n])
{
if (s[i]=='a') putchar('B');
else if (s[i]=='b' || s[i]=='c') putchar('A');
else if (Orz[all[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 (Orz[all[i]]=='A') putchar('C');
else putchar('B');
}
return 1;
}
int d;
bool flag;
inline void dfs(int dep)
{
if (dep>d)
{
if (!flag) flag=solve();
if (flag) exit(0);
return ;
}
Orz[dep]='A',dfs(dep+1);
Orz[dep]='B',dfs(dep+1);
}
int main()
{
read(n);read(tmp);
scanf("%s",s+1);
for (int i=1; i<=n; ++i)
if (s[i]=='x') all[i]=++d;
read(m);
for (int i=1; i<=m; ++i) read(a1[i]),a2[i]=get(),read(b1[i]),b2[i]=get();
dfs(1);
if (!flag) puts("-1");
return 0;
}