1032. 游戏

题目链接

1032. 游戏

狂野飙车是小 \(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\)”(不含双引号)。

输入格式

输入第一行包含两个非负整数 \(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\),含义见题目描述。

输出格式

输出一行。

若无解输出 “\(-1\)”(不含双引号)。

若有解,则包含一个长度为 \(n\) 的仅包含大写字母 \(A、B、C\) 的字符串,表示小 \(L\) 在这 \(n\) 场游戏中如何安排赛车的使用。

如果存在多组解,输出其中任意一组即可。

数据范围

image

输入样例:

3 1
xcc
1
1 A 2 B

输出样例:

ABA

样例解释

\(L\) 计划进行 \(3\) 场游戏,其中第 \(1\) 场的地图类型是 \(x\),适合所有赛车,第 \(2\) 场和第 \(3\) 场的地图是 \(c\),不适合赛车 \(C\)

\(L\) 希望:若第 \(1\) 场游戏使用赛车 \(A\),则第 \(2\) 场游戏使用赛车 \(B\)

那么为这 \(3\) 场游戏分别安排赛车 \(A、B、A\) 可以满足所有条件。

若依次为 \(3\) 场游戏安排赛车为 \(BBB\)\(BAA\) 时,也可以满足所有条件,也被视为正确答案。

但依次安排赛车为 \(AAB\)\(ABC\) 时,因为不能满足所有条件,所以不被视为正确答案。

解题思路

2-SAT

对于 \(a\),其只能使用 \(A\)\(B\),对于 \(b\),其只能使用 \(a\)\(c\),对于 \(c\),其只能使用 \(A\)\(B\),对于 \(x\),其可以使用 \(A\)\(B\)\(C\),显然这是一个 2-SAT 和 3-SAT 结合的问题,即如果不考虑 \(x\) 存在的情况(即只存在 2-SAT 的情况),对于若干个条件,即如果第 \(i\) 场使用 \(x\),则第 \(j\) 场应该使用 \(y\),如果第 \(i\) 场本身就不能使用 \(x\),则显然该条件没用,可以忽略,否则如果第 \(j\) 场本身不能使用 \(y\),则应该使条件不成立,即第 \(i\) 场不应该使用 \(x\),否则如果第 \(j\) 场能使用 \(y\) 的话,则应该使第 \(i\) 场使用 \(x\) 这个命题表示的节点指向第 \(j\) 场使用 \(y\) 这个命题表示的节点,同时逆否命题也需要加入边,但是回到问题本身, 3-SAT 是一个 NPC 问题,但是由于 \(x\) 的个数不是很多,但如果暴力枚举所有 \(x\) 的值的话也不行,但可以将 3-SAT 问题转化为 2-SAT 问题,即对于有 \(x\) 的场次来说,其一定是选 \(B\)\(C\),或者选 \(A\)\(C\),即其可以等价于两种 2-SAT,共有 \(2^d\) 种组合,这样就将问题完全转化为 2-SAT 问题

  • 时间复杂度:\(O(2^d\times (n+m)\)

代码

// Problem: 游戏
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1034/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=100005,M=2e5+5;
int n,d,m;
char s[N];
int h[N],ne[M],e[M],idx;
int pos[10];
int dfn[N],low[N],timestamp,stk[N],top,scc_cnt,id[N];
bool in_stk[N];
struct Op
{
	int x,y;
	char a,b;
}op[M];
void add(int a,int b)
{
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void tarjan(int x)
{
	dfn[x]=low[x]=++timestamp;
	stk[++top]=x,in_stk[x]=true;
	for(int i=h[x];~i;i=ne[i])
	{
		int y=e[i];
		if(!dfn[y])
		{
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(in_stk[y])
			low[x]=min(low[x],dfn[y]);
	}
	if(low[x]==dfn[x])
	{
		int y;
		scc_cnt++;
		do
		{
			y=stk[top--];
			in_stk[y]=false;
			id[y]=scc_cnt;
		}while(y!=x);
	}
}
int get(int x,char a,int t)
{
	a-='A';
	char b=s[x]-'a';
	if(((b+1)%3==a)^t)return x<<1|1;
	return x<<1;
}
char put(int x,int t)
{
	int y=s[x]-'a';
	return 'A'+(y+t)%3;
}
bool work()
{
	memset(h,-1,sizeof h);
	memset(dfn,0,sizeof dfn);
	idx=timestamp=scc_cnt=0;
	for(int i=0;i<m;i++)
	{
		int x=op[i].x-1,y=op[i].y-1;
		char a=op[i].a,b=op[i].b;
		if(a+32!=s[x])
		{
			if(b+32!=s[y])add(get(x,a,1),get(y,b,1)),add(get(y,b,0),get(x,a,0));
			else
				add(get(x,a,1),get(x,a,0));
		}
	}
	for(int i=0;i<2*n;i++)
		if(!dfn[i])tarjan(i);
	for(int i=0;i<n;i++)
		if(id[i<<1]==id[i<<1|1])return false;
	for(int i=0;i<n;i++)
		if(id[i<<1]<id[i<<1|1])putchar(put(i,1));
		else
			putchar(put(i,2));
	return true;
}
int main()
{
    scanf("%d%d",&n,&d);
    scanf("%s",s);
    for(int i=0,j=0;s[i];i++)
    	if(s[i]=='x')pos[j++]=i;
    scanf("%d",&m);
    for(int i=0;i<m;i++)scanf("%d %c %d %c",&op[i].x,&op[i].a,&op[i].y,&op[i].b);
    for(int i=0;i<1<<d;i++)
    {
    	for(int j=0;j<d;j++)
    		if(i>>j&1)s[pos[j]]='a';
    		else
    			s[pos[j]]='b';
    	if(work())return 0;
    }
    puts("-1");
    return 0;
}
posted @ 2022-12-04 16:08  zyy2001  阅读(27)  评论(0编辑  收藏  举报