对于 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,共有 2d 种组合,这样就将问题完全转化为 2-SAT 问题
时间复杂度:O(2d×(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_pairusingnamespace std;
typedeflonglong LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> boolchkMax(T &x, T y){ return (y > x) ? x = y, 1 : 0; }
template <typename T> boolchkMin(T &x, T y){ return (y < x) ? x = y, 1 : 0; }
template <typename T> voidinlineread(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;
}
constint 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];
structOp{
int x,y;
char a,b;
}op[M];
voidadd(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
voidtarjan(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]);
}
elseif(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);
}
}
intget(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;
}
charput(int x,int t){
int y=s[x]-'a';
return'A'+(y+t)%3;
}
boolwork(){
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));
elseadd(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])returnfalse;
for(int i=0;i<n;i++)
if(id[i<<1]<id[i<<1|1])putchar(put(i,1));
elseputchar(put(i,2));
returntrue;
}
intmain(){
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())return0;
}
puts("-1");
return0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!