【BZOJ4945】[Noi2017]游戏

题目描述

题解:2-SAT学艺不精啊!

这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起!

因为x要么不是A要么不是B,所以直接2^8枚举所有x就行了。然后就变成了一个2-SAT问题。假设有两场游戏1,2,分别可以使用的地图为A1,A2,B1,B2,如果有一个限制是1 A 2 A,那么选A1就必须选A2,然后我这个沙茶就开开心心的拿了55分。

为什么不对?我建出来的图显然不对偶啊!考虑逆否命题,选A1就必须选A2,那么选B2就必须选B1啊!然后跑2-SAT+拓扑排序输出方案即可。

特别地,如果选A1就必须选A2,但是A1不能选,那么我们可以直接无视这个条件。如果选A1就必须选A2,但是A2不能选,那么A1也不能选, 于是就连一条A1->B1的边(你可以理解为这样以来,在反向图中B1的拓扑序在A1前面,所以会先选B1。但真正用意好像不是这个~)。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#define P(A,B) ((B-1)*n+A)
using namespace std;
const int maxn=200010;
int n,D,m,sum,tot,top,cnt,flag;
int to[maxn],next[maxn],head[maxn],tt[maxn],nn[maxn],hh[maxn],op[maxn],ot[maxn];
int del[maxn],ins[maxn],dep[maxn],low[maxn],sta[maxn],bel[maxn],pos[10];
int pa[maxn],pb[maxn],pc[maxn],pd[maxn],color[maxn],d[maxn];
char str[maxn],c1[5],c2[5],ans[maxn];
queue<int> q;
void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void ADD(int a,int b)
{
tt[cnt]=b,nn[cnt]=hh[a],hh[a]=cnt++;
}
void tarjan(int x)
{
dep[x]=low[x]=++tot,ins[x]=1,sta[++top]=x;
for(int i=hh[x];i!=-1;i=nn[i])
{
int y=tt[i];
if(!dep[y]) tarjan(y),low[x]=min(low[x],low[y]);
else if(ins[y]) low[x]=min(low[x],dep[y]);
}
if(dep[x]==low[x])
{
int t;
sum++;
do
{
t=sta[top--],ins[t]=0,bel[t]=sum;
}while(t!=x);
}
}
void check()
{
memset(hh,-1,sizeof(hh));
memset(dep,0,sizeof(dep));
cnt=tot=sum=0;
int i,a,b,c;
for(i=1;i<=n;i++)
{
a=(str[i]-'a')*n+i,b=(a-1+n)%(3*n)+1,c=(b-1+n)%(3*n)+1;
del[a]=1,del[b]=del[c]=0;
op[b]=c,op[c]=b;
}
for(i=1;i<=m;i++)
{
a=pc[i]*n+pa[i],b=pd[i]*n+pb[i];
if(a==b||del[a]) continue;
if(pa[i]==pb[i]||del[b])
{
ADD(a,op[a]);
continue;
}
ADD(op[b],op[a]),ADD(a,b);
}
for(i=1;i<=3*n;i++) if(!del[i]&&!dep[i]) tarjan(i);
for(i=1;i<=3*n;i++)
{
if(del[i]) continue;
if(bel[op[i]]==bel[i]) return ;
else ot[bel[op[i]]]=bel[i],ot[bel[i]]=bel[op[i]];
}
flag=1;
}
void dfs(int x)
{
if(x==D+1)
{
check();
return ;
}
str[pos[x]]='a',dfs(x+1);
if(flag) return ;
str[pos[x]]='b',dfs(x+1);
}
void DFS(int x)
{
if(color[x]!=-1) return ;
color[x]=0,color[ot[x]]=1;
for(int i=head[x];i!=-1;i=next[i]) DFS(to[i]);
}
int main()
{
scanf("%d%d%s%d",&n,&D,str+1,&m);
int i,j,u;
for(i=1;i<=n;i++) if(str[i]=='x') pos[++pos[0]]=i;
for(i=1;i<=m;i++)
{
scanf("%d%s%d%s",&pa[i],c1,&pb[i],c2),pc[i]=c1[0]-'A',pd[i]=c2[0]-'A';
}
dfs(1);
if(!flag)
{
printf("-1");
return 0;
}
memset(head,-1,sizeof(head));
memset(color,-1,sizeof(color));
cnt=0;
for(i=1;i<=3*n;i++) if(!del[i])
{
for(j=hh[i];j!=-1;j=nn[j]) if(bel[tt[j]]!=bel[i]) d[bel[i]]++,add(bel[tt[j]],bel[i]);
}
for(i=1;i<=sum;i++) if(!d[i]) q.push(i);
while(!q.empty())
{
u=q.front(),q.pop();
for(i=head[u];i!=-1;i=next[i])
{
d[to[i]]--;
if(!d[to[i]]) q.push(to[i]);
}
if(color[u]!=-1) continue;
DFS(ot[u]);
}
for(i=1;i<=3*n;i++) if(!del[i]&&color[bel[i]]==1) ans[(i-1)%n]=(i-1)/n+'A';
printf("%s",ans);
return 0;
}

【BZOJ4945】[Noi2017]游戏 2-SAT的更多相关文章

  1. [BZOJ4945][Noi2017]游戏 2-sat

    对于所有的x,我们枚举他的地图类型,事实上我们只需要枚举前两种地形就可以覆盖所有的情况. 之后就变成了裸的2-sat问题. 对于一个限制,我们分类讨论: 1.h[u]不可选,跳过 2.h[v]不可选, ...

  2. [bzoj4945][Noi2017]游戏

    题目大意:有$n$个位置,有三种数,每个位置只可以填一种数,$d(d\leqslant8)$个位置有三种选择,其他位置只有两种选择.有一些限制,表示第$i$个位置选了某种数,那么第$j$个位置就只能选 ...

  3. P3825 [NOI2017]游戏

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

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

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

  5. BZOJ4945 & 洛谷3825 & UOJ317:[NOI2017]游戏——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4945 https://www.luogu.org/problemnew/show/P3825 ht ...

  6. 【bzoj4945】[Noi2017]游戏(搜索+2-sat)

    bzoj 洛谷 题意: 现在有\(a,b,c\)三种车,每个赛道可能会存在限制:\(a\)表示不能选择\(a\)类型的赛车,\(b,c\)同理:\(x\)表示该赛道不受限制,但\(x\)类型的个数$\ ...

  7. 并不对劲的bzoj4945:loj2305:uoj317:p3825[NOI2017]游戏

    题目大意 2-SAT,其中有\(d\)(\(d\leq 8\))个点是\(3-SAT\). 题解 枚举\(d\)个点不取三个中(假设三个为\(a,b,c\))的哪一个,然后整体变成做\(2-SAT\) ...

  8. bzoj3825 NOI2017 游戏

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

  9. [NOI2017]游戏(2-SAT)

    这是约半年前写的题解了,就搬过来吧 感觉这是NOI2017最水的一题(当然我还是不会2333),因为是一道裸的2-SAT.我就是看着这道题学的2-SAT 算法一:暴力枚举.对于abc二进制枚举,对于x ...

随机推荐

  1. Java编程风格学习(一)

    最近在看一本有关Java编程规范的书,书中精炼阐述了使用java语言时应该遵循的一些原则.接下来的一段时间我将在这里总结我的学习内容,也希望这一系列文章能够对有需要的人有所帮助.不考虑任何编码规范的代 ...

  2. 10.1综合强化刷题 Day2

    a[问题描述]你是能看到第一题的 friends呢.                                                —— hja世界上没有什么比卖的这 贵弹丸三还令人绝 ...

  3. 解决百度ueditor配置上传目录为外部目录时,项目启动访问不到图片的问题。

    如图所示,公司项目用到了百度的ueditor,配置的上传目录并不在项目根目录下,而是在外部目录中.于是在上传图片时,出现了无法获取图片的问题. 解决方法:添加该目录至tomcat项目部署目录中,如下图 ...

  4. 记录一次eclipse的错误:“server tomcat v7.0 server at localhost was unable to start within 45 seconds”的问题解决思路

    如果配到上述问题,可以参考网上查找的方法,如下: http://stackoverflow.com/questions/6468520/server-tomcat-v6-0-server-at-loc ...

  5. C++输入和输出中进制问题

    默认下都是十进制 int i, j, k, l; cin>>oct>>i; //输入为八进制数 cin>>hex>>j; //输入为十六进制数 cin& ...

  6. win7安装mysql解压缩版

    http://blog.csdn.net/u013067166/article/details/49951577

  7. Mycat本地模式的自增长分表操作

    Mycat对表t_rc_rule_monitor做分表操作 在mysql上执行(没有t_rc_rule_monitor) DROP TABLE IF EXISTS t_rc_rule_monitor; ...

  8. WPF 基础到企业应用系列5——WPF千年轮回 续前缘

    一.摘要 首先非常高兴这个系列能得到大家的关注和支持,前端时间身体状况不适,所以暂停了更新,对此表示非常抱歉,以后会逐渐加快进度.只是因为这是一个非常长的系列,我也想把它写好,所以以后也会慢慢来,在这 ...

  9. Vmware+gdb调试Linux内核——工欲善其事,必先利其器

    今天我最终忍受不了qemu的低速跟不可理喻的各种bug,開始寻找新的调试内核的方法.然后想到了Vmware,那么成熟的虚拟机怎么可能调试不了内核.于是尝试了一番,发现结果很的棒!所以立刻奋笔疾书.把这 ...

  10. Java中执行存储过程和函数

    装载于:http://www.cnblogs.com/liunanjava/p/4261242.html 一.概述 如果想要执行存储过程,我们应该使用 CallableStatement 接口. Ca ...