这是约半年前写的题解了,就搬过来吧

感觉这是NOI2017最水的一题(当然我还是不会2333),因为是一道裸的2-SAT。我就是看着这道题学的2-SAT

算法一:暴力枚举。对于abc二进制枚举,对于x则采用三进制枚举即可,复杂度O(3^d*2^(n-d)),再进行适当剪支,期望得分:40~50

算法二:对于d=0的点,采用2-SAT算法,这是最裸的2-SAT,这样,复杂度为O(n+m),综合算法一,期望得分为60

算法三:不妨对于d个x,采用三进制枚举,枚举a/b/c,再做裸的2-SAT即可,复杂度O(3^d*(n+m)),期望得分:75~90,如果常数小可以X过去

算法四:不难发现,三进制枚举不但效率慢,而且难写、没必要,对于判断会很复杂,不如只枚举禁止使用A/B,因为这样已经包含了A/B/C三种赛车,所以可以这么做(因为题目只要求一组解),复杂度O(2^d*(n+m)),期望得分:100

难点:2-SAT和输出方案的2-SAT

注意:选A就选B等价于选B'就选A’,所以需要连接双向边!!

不说了上code

#include<bits/stdc++.h>
#define mem(x) memset(x,0,sizeof x)
using namespace std;
const int N=2e5+;
int n,m,d,scc,cnt,top,c[N],s1[N],t1[N],dfn[N],low[N],part[N],hd[N],v[N],nxt[N],q[N];
char s[N],s2[N],t2[N],t[N];
bool vis[N],flag;
void add(int x,int y){v[++cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt;}
int opp(int x){return x>n?x-n:x+n;}
int jisuan(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;
}
void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
q[++top]=u;
vis[u]=;
for(int i=hd[u];i;i=nxt[i])
if(!dfn[v[i]])
{
tarjan(v[i]);
low[u]=min(low[u],low[v[i]]);
}
else if(vis[v[i]])low[u]=min(low[u],dfn[v[i]]);
if(dfn[u]==low[u])
{
part[u]=++scc;
vis[u]=;
int now;
do{
now=q[top--];
vis[now]=;
part[now]=scc;
}while(now!=u);
}
}
void solve()
{
scc=cnt=;
mem(dfn);mem(low);mem(part);mem(hd);mem(nxt);
for(int i=;i<=m;i++)
if(s[s1[i]]!='x'&&s[t1[i]]!='x'&&s[s1[i]]-!=s2[i])
{
int u=jisuan(s1[i],s2[i]),v;
if(s[t1[i]]-==t2[i])add(u,opp(u));
else{
v=jisuan(t1[i],t2[i]);
add(u,v);add(opp(v),opp(u));
}
}
else{
char S=s[s1[i]],T=s[t1[i]];
int x=c[s1[i]],y=c[t1[i]];
if(S=='x'&&T=='x'&&s2[i]!=t[x])
{
int u=jisuan(s1[i],s2[i]),v;
if(t2[i]==t[y])add(u,opp(u));
else{
v=jisuan(t1[i],t2[i]);
add(u,v);add(opp(v),opp(u));
}
}
else if(S=='x'&&T!='x'&&s2[i]!=t[x])
{
int u=jisuan(s1[i],s2[i]),v;
if(s[t1[i]]-==t2[i])add(u,opp(u));
else{
v=jisuan(t1[i],t2[i]);
add(u,v);add(opp(v),opp(u));
}
}
else if(S!='x'&&T=='x'&&s[s1[i]]-!=s2[i])
{
int u=jisuan(s1[i],s2[i]),v;
if(t2[i]==t[y])add(u,opp(u));
else{
v=jisuan(t1[i],t2[i]);
add(u,v);add(opp(v),opp(u));
}
}
}
cnt=;
for(int i=;i<=n*;i++)if(!dfn[i])tarjan(i);
for(int i=;i<=n;i++)if(part[i]==part[i+n])return;
for(int i=;i<=n;i++)
if(part[i]<part[i+n])
{
if(s[i]=='a')printf("B");
else if(s[i]=='b'||s[i]=='c')printf("A");
else if(t[c[i]]=='A')printf("B");
else printf("A");
}
else{
if(s[i]=='a'||s[i]=='b')printf("C");
else if(s[i]=='c')printf("B");
else if(t[c[i]]=='A')printf("C");
else printf("B");
}
flag=;
}
void fact(int k)
{
if(flag)return;
if(k>d){solve();return;}
t[k]='A';fact(k+);t[k]='B';fact(k+);
}
int main()
{
scanf("%d%d",&n,&d);
d=;
scanf("%s",s+);
for(int i=;i<=n;i++)if(s[i]=='x')c[i]=++d;
scanf("%d",&m);
for(int i=;i<=m;i++)scanf("%d %c%d %c",&s1[i],&s2[i],&t1[i],&t2[i]);
fact();
if(!flag)puts("-1");
}

[NOI2017]游戏(2-SAT)的更多相关文章

  1. P3825 [NOI2017]游戏

    题目 P3825 [NOI2017]游戏 做法 \(x\)地图外的地图好做,模型:\((x,y)\)必须同时选\(x \rightarrow y,y^\prime \rightarrow x^\pri ...

  2. 【BZOJ4945】[Noi2017]游戏 2-SAT

    [BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么 ...

  3. [Luogu P3825] [NOI2017] 游戏 (2-SAT)

    [Luogu P3825] [NOI2017] 游戏 (2-SAT) 题面 题面较长,略 分析 看到这些约束,应该想到这是类似2-SAT的问题.但是x地图很麻烦,因为k-SAT问题在k>2的时候 ...

  4. bzoj3825 NOI2017 游戏

    题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行nn 场游戏,每场游戏使用一张地 ...

  5. NOI2017 [NOI2017]游戏 【2-sat】

    题目 题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行nn 场游戏,每场游戏使用 ...

  6. bzoj 4945: [Noi2017]游戏

    Description Solution 首先我们发现一个位置如果不是 \('x'\),那么就只有两种选择 而 \('x'\) 的个数小于等于 \(8\),直接枚举是哪个就好了 然后就是 \(2-sa ...

  7. [NOI2017]游戏

    题目描述 http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf 题解 如果说没有x的话,那么每一局只能有两种选择,可以描述为是/非,每条限制也可以 ...

  8. 洛谷3825 [NOI2017]游戏 2-sat

    原文链接http://www.cnblogs.com/zhouzhendong/p/8146041.html 题目传送门 - 洛谷3825 题解 我们考虑到地图中x的个数很少,最多只有8个. 所以我们 ...

  9. Luogu3825 NOI2017 游戏 2-SAT

    传送门 第一眼看上去似乎是一个3-SAT问题 然而\(d \leq 8\)给我们的信息就是:暴力枚举 枚举\(x\)型地图变成\(a\)型地图还是\(b\)型地图(实际上不要枚举\(c\),因为\(a ...

随机推荐

  1. 移动APP用例设计中的关键点(转载)

    http://www.51testing.com/html/52/n-4421752.html 在测试工作中我们需要不断的总结和储备自己的知识和经验,譬如具备特定属性.环境以及场景,如:PC,手机,智 ...

  2. SQL之CASE WHEN用法详解[1]

    简单CASE WHEN函数: CASE SCORE WHEN 'A' THEN '优' ELSE '不及格' END CASE SCORE WHEN 'B' THEN '良' ELSE '不及格' E ...

  3. oss命令使用

    下载文件夹 ossutil64 cp oss://folder/ out_folder/ -r --jobs 20

  4. JQuery operate xml

    msg is <?xml ?> <Parameters> <WorkflowName>...</WorkflowName> </Parameter ...

  5. Nginx geo模块

    geo 模块默认编译进nginx 可以通过--without-http_geo_module禁用 Syntax: geo [$address] $variable { ... } Default: — ...

  6. JarvisOJ Basic easyRSA

    还记得veryeasy RSA吗?是不是不难?那继续来看看这题吧,这题也不难. 已知一段RSA加密的信息为:0xdc2eeeb2782c且已知加密所用的公钥: (N=322831561921859 e ...

  7. ftell 的使用

    ftell一般用于读取文件的长度,下面补充一个例子,读取文本文件中的内容: #include <stdio.h> #include <stdlib.h> int main() ...

  8. linux中安装gcc

    在使用CentOS的yum -y install  时 可以先进入  /etc/yum.repos.d/ 文件下,将CentOS-Base.repo文件名改为CentOS-Base.repo.bak使 ...

  9. BZOJ3724PA2014Final Krolestwo——欧拉回路+构造

    题目描述 你有一个无向连通图,边的总数为偶数.设图中有k个奇点(度数为奇数的点),你需要把它们配成k/2个点对(显然k被2整除).对于每个点对(u,v),你需要用一条长度为偶数(假设每条边长度为1)的 ...

  10. windows 系统错误码总结

    windows 错误码大全: 操作成功完成. 功能错误. 系统找不到指定的文件. 系统找不到指定的路径. 系统无法打开文件. 拒绝访问. 句柄无效. 存储控制块被损坏. 存储空间不足,无法处理此命令. ...