P3825 [NOI2017] 游戏
不禁让人加深了对 2-SAT 的感知度。
先考虑 的情况,这时候发现每个赛道其实只有两种取值,所以可以考虑 2-SAT,具体的,把每个点能取的两种取值看成 和 ,然后按照题目的限制连边即可。
然后发现 的范围很小,不难想到暴力取 x
的点应该用什么赛车,时间复杂度是 的,难以通过。
不妨想到我们最开始 的时候,我们定义了一个点是有两种取值的,比如说当前赛道是 a
,实际上我们就已经把使用了赛车 B
和 C
都考虑进去了,所以我们只需要枚举两种赛道,这样就能覆盖到取三种赛车的情况。
这样的话时间复杂度就被优化到了 ,可以通过本题。
细节不少,注意每次跑的时候清空要完全,以及在连边的时候的判断情况要想清楚。
#include<bits/stdc++.h>
using namespace std;
const int N =2e5+10;
vector<int> g[N];
char s[N],ans[N],ch[N],ch1[N];
int low[N],dfn[N],vis[N],F[N],tot,SCC;
int n,m,d,op[N],op1[N];
stack<int> sta;
bool f=false;
int change(char Ch,int dis){
if(s[dis]=='a') return ((Ch=='B')?dis:dis+n);
else if(s[dis]=='b') return ((Ch=='A')?dis:dis+n);
else return ((Ch=='A')?dis:dis+n);
}
void build(){
for(int i=1;i<=m;i++){
int u=change(ch[i],op[i]),v=change(ch1[i],op1[i]);
if(ch[i]==s[op[i]]-'a'+'A') continue;
if(ch1[i]==s[op1[i]]-'a'+'A') g[u].push_back(((u>n)?u-n:u+n));
else g[u].push_back(v),g[((v>n)?v-n:v+n)].push_back((u>n)?u-n:u+n);
}
}
void Clear(){
for(int i=1;i<=2*n;i++) g[i].clear(),low[i]=dfn[i]=0,F[i]=0,vis[i]=0;
SCC=tot=0;
}
void Tarjan(int u){
dfn[u]=low[u]=++tot,vis[u]=1,sta.push(u);
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if(!dfn[v]) Tarjan(v),low[u]=min(low[u],low[v]);
else if(vis[v]==1) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
SCC++;
while(!sta.empty()&&sta.top()!=u) F[sta.top()]=SCC,vis[sta.top()]=2,sta.pop();
F[sta.top()]=SCC,vis[sta.top()]=2,sta.pop();
}
}
void Slove(){
build();
for(int i=1;i<=2*n;i++) if(!dfn[i]) Tarjan(i);
for(int i=1;i<=n;i++) if(F[i]==F[i+n]) {Clear();return ;}
for(int i=1;i<=n;i++){
if(s[i]=='a') ans[i]=((F[i]>F[i+n])?'C':'B');
else if(s[i]=='b') ans[i]=((F[i]>F[i+n])?'C':'A');
else ans[i]=((F[i]>F[i+n])?'B':'A');
}
Clear(),f=true;
}
void dfs(int dis){
if(dis==n+1){Slove();return ;}
if(s[dis]=='x') s[dis]='a',dfs(dis+1),s[dis]='b',dfs(dis+1),s[dis]='x';
else dfs(dis+1);
}
int main(){
cin>>n>>d,scanf("%s",s+1),cin>>m;
for(int i=1;i<=m;i++) cin>>op[i]>>ch[i]>>op1[i]>>ch1[i];
dfs(1);
// Slove();
// for(int i=1;i<=2*n;i++) cout<<F[i]<<" ";
if(f==false) cout<<-1<<endl,exit(0);
else for(int i=1;i<=n;i++) cout<<ans[i];
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧