NOI2017-游戏-2sat
NOI2017-游戏-2sat
https://www.luogu.com.cn/problem/P3825
题意:有三种赛车A,B,C,以及用字符串
同时保证了
如果
- 如果
,那么意味着若 则 这句话里,前提是一定不能选的(恒假),这个公式是恒真的,所以不用连边。 - 好了,那如果
,前提可能真可能假,那再看结论:- 如果
,结论恒为假,2-sat其实不太允许我们在 和 里添加第三种状态(这一点我没有严格证明过,但是一开始添加了一个叫做“恒假”的状态,wa了一片,不承认排中律的话好像会变成 3-sat 或者更困难的情况)。这种时候结论恒为假,为了保证”若 则 “,那就一定要让 是假的,所以就连一条 的边。 - 否则
,这时候就只要 以及 两条边。
- 如果
好了现在有至多
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0) using namespace std; const int N=5e4+5; const int M=1e5+5; int n,d,m,bl[N<<1]; int a[M][2],idx[N][3],rev[N][3]; char ch[M][2],col[N<<1]; string s; namespace SCC{ struct edge{ int to,nxt; }edges[M<<1]; int head[N<<1],cnt; int low[N<<1],dfn[N<<1],dfscnt,scc; bool in_stack[N<<1]; stack<int> S; void init(int _n){ dfscnt=scc=cnt=0; rep(i,1,_n)low[i]=dfn[i]=head[i]=bl[i]=in_stack[i]=0; } void add(int u,int v){ edges[++cnt]=(edge){v,head[u]}; head[u]=cnt; } void tarjan(int x){ low[x]=dfn[x]=++dfscnt; S.push(x);in_stack[x]=1; for(int i=head[x];i;i=edges[i].nxt){ int to=edges[i].to; if(!dfn[to]){ tarjan(to); low[x]=min(low[x],low[to]); }else if(in_stack[to]) low[x]=min(low[x],dfn[to]); } if(low[x]==dfn[x]){ ++scc; bool tag=0; while(1){ bl[S.top()]=scc; if(S.top()==x)tag=1; in_stack[S.top()]=0; S.pop(); if(tag)break; } } } }; void work(){ int mx=2*n; SCC::init(mx); rep(i,1,n){ rep(j,0,2)idx[i][j]=rev[i][j]=-1; col[i]=((s[i-1]-'A'+1)%3+'A'); col[i+n]=((s[i-1]-'A'+2)%3+'A'); idx[i][col[i]-'A'] =i; idx[i][col[i+n]-'A']=i+n; rev[i][col[i]-'A'] =i+n; rev[i][col[i+n]-'A']=i; } rep(tc,1,m){//2*m int i=a[tc][0],j=a[tc][1]; char hi=ch[tc][0],hj=ch[tc][1]; if(hi!=s[i-1]){ if(hj==s[j-1]){ int u=idx[i][hi-'A']; if(u<=n)SCC::add(u,u+n); else SCC::add(u,u-n); }else{ SCC::add(idx[i][hi-'A'],idx[j][hj-'A']); SCC::add(rev[j][hj-'A'],rev[i][hi-'A']); } } } rep(i,1,mx)if(!bl[i])SCC::tarjan(i); rep(i,1,n)if(bl[i]==bl[i+n])return; rep(i,1,n){ if(bl[i]<bl[i+n])cout<<col[i]; else cout<<col[i+n]; } exit(0); } int main(){ fastio; cin>>n>>d>>s>>m; rep(i,0,n-1)s[i]=s[i]-'a'+'A'; rep(i,1,m)cin>>a[i][0]>>ch[i][0]>>a[i][1]>>ch[i][1]; vector<int> pos; rep(i,0,n-1)if(s[i]=='X')pos.push_back(i); for(int S=0;S<(1<<d);S++){ rep(i,0,d-1){ if((S>>i)&1)s[pos[i]]='A'; else s[pos[i]]='B'; } work(); } cout<<-1; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!