BZOJ 4945 NOI2017 游戏 搜索+2-SAT
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4945
分析:
首先考虑没有x的情况,发现有一个明显的推理模型,容易看出来可以用2-SAT做。
然后考虑有x的情况,发现最多只有8个x,不难想到可以搜索每个x为a,b,c中的哪个然后跑2-SAT。但是算算时间发现会T。
再仔细分析,发现只需要枚举两种情况就可以了。因为可行的对象已经全部在这两种情况里面包含了!
发现真的tarjan比另外一个算法快......事实证明另外一个算法(我叫不出名字ORZ)是可以被卡成O(NM)的。(从此入了tarjan的教。。。)
此题细节令人开心。
时间复杂度O((N+M)*2^x)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int maxn=;
const int maxm=; int N,D,M;
char S[maxn];
struct edge{ int to,next; }E[maxm<<];
struct data{ int i,j; char hi,hj; }da[maxm];
int first[maxn<<],_first[maxn<<],np,pos[],cnt,stk[maxn<<],top;
int dfn[maxn<<],sccno[maxn<<],dfs_clock,scc_cnt,low[maxn<<];
bool bad[maxn<<],_bad[maxn<<]; void _scanf(int &x)
{
x=;
char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
}
void _scanf(char &x)
{
x=getchar();
while(!isalpha(x)) x=getchar();
}
void add_edge(int u,int v,int *f)
{
E[++np]=(edge){v,f[u]};
f[u]=np;
}
int id(int i,char a)
{
if(S[i]=='a') return i*-(a=='B'?:);
return i*-(a=='A'?:);
}
int _id(int i,bool k)
{
if(k) return S[i]=='a'?:;
return S[i]=='c'?:;
}
void data_in()
{
_scanf(N);_scanf(D);scanf("%s",S+);_scanf(M);
int a,b; char hi,hj;
for(int i=;i<=N;i++)
if(S[i]=='x') pos[++cnt]=i;
cnt=;
for(int i=;i<=M;i++){
_scanf(a);_scanf(hi);_scanf(b);_scanf(hj);
if(S[a]-hi==) continue;
if(S[a]=='x'||S[b]=='x'){
da[++cnt]=(data){a,b,hi,hj};
continue;
}
if(S[b]-hj==){ bad[id(a,hi)]=; continue; }
a=id(a,hi),b=id(b,hj);
add_edge(a,b,first); add_edge((b-^)+,(a-^)+,first);
}
}
void tarjan_scc(int i)
{
if(_bad[i]) return;
dfn[i]=low[i]=++dfs_clock;
stk[++top]=i;
for(int p=_first[i];p;p=E[p].next){
int j=E[p].to;
if(dfn[j]){
if(!sccno[j]) low[i]=min(low[i],dfn[j]);
continue;
}
tarjan_scc(j);
low[i]=min(low[i],low[j]);
}
if(low[i]==dfn[i]){
scc_cnt++;
while(stk[top]!=i) sccno[stk[top--]]=scc_cnt;
sccno[stk[top--]]=scc_cnt;
}
}
bool judge()
{
memset(dfn,,sizeof(dfn));
memset(sccno,,sizeof(sccno));
memset(low,,sizeof(low));
dfs_clock=scc_cnt=top=;
for(int i=;i<=N*;i++)
if(!dfn[i]) tarjan_scc(i);
for(int i=;i<=N;i++)
if(sccno[i*-]==sccno[i*]) return ;
return ;
}
bool run(int i)
{
if(i>D){
memcpy(_first,first,sizeof(first));
memcpy(_bad,bad,sizeof(bad));
int tmp=np,a,b;
for(int k=;k<=cnt;k++){
if(S[da[k].i]-da[k].hi==) continue;
if(S[da[k].j]-da[k].hj==){ _bad[id(da[k].i,da[k].hi)]=; continue; }
a=id(da[k].i,da[k].hi),b=id(da[k].j,da[k].hj);
add_edge(a,b,_first); add_edge((b-^)+,(a-^)+,_first);
}
np=tmp;
return judge();
}
S[pos[i]]='a'; if(run(i+)) return ;
S[pos[i]]='b'; if(run(i+)) return ;
return ;
}
void work()
{
if(!run()) printf("%d\n",-);
else{
for(int i=;i<=N;i++){
if(!sccno[i*-]) putchar('A'+_id(i,));
else if(!sccno[i*]) putchar('A'+_id(i,));
else if(sccno[i*]<sccno[i*-]) putchar('A'+_id(i,));
else putchar('A'+_id(i,));
}
putchar('\n');
}
}
int main()
{
data_in();
work();
return ;
}
BZOJ 4945 NOI2017 游戏 搜索+2-SAT的更多相关文章
- bzoj 4945: [Noi2017]游戏
Description Solution 首先我们发现一个位置如果不是 \('x'\),那么就只有两种选择 而 \('x'\) 的个数小于等于 \(8\),直接枚举是哪个就好了 然后就是 \(2-sa ...
- 【刷题】BZOJ 4945 [Noi2017]游戏
Description http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf Solution 字符串里的'x'看起来很烦,于是考虑枚举这些'x' ...
- P3825 [NOI2017]游戏
题目 P3825 [NOI2017]游戏 做法 \(x\)地图外的地图好做,模型:\((x,y)\)必须同时选\(x \rightarrow y,y^\prime \rightarrow x^\pri ...
- 【BZOJ4945】[Noi2017]游戏 2-SAT
[BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么 ...
- [Luogu P3825] [NOI2017] 游戏 (2-SAT)
[Luogu P3825] [NOI2017] 游戏 (2-SAT) 题面 题面较长,略 分析 看到这些约束,应该想到这是类似2-SAT的问题.但是x地图很麻烦,因为k-SAT问题在k>2的时候 ...
- BZOJ 4945 UOJ #317 NOI2017 游戏 2-SAT 拓扑排序
http://uoj.ac/problem/317 https://www.lydsy.com/JudgeOnline/problem.php?id=4945 我现在的程序uoj的额外数据通过不了,b ...
- 【bzoj4945】[Noi2017]游戏(搜索+2-sat)
bzoj 洛谷 题意: 现在有\(a,b,c\)三种车,每个赛道可能会存在限制:\(a\)表示不能选择\(a\)类型的赛车,\(b,c\)同理:\(x\)表示该赛道不受限制,但\(x\)类型的个数$\ ...
- NOIp 2011 mayan游戏 搜索
题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...
- POJ3322-经典的游戏搜索问题
临近毕业真是各种琐事多,好不容易写完几万字蛋疼的论文,又接着户口档案挂靠,毕业旅游,20多个离校盖章,签证被check了几个星期还没消息,希望8月初能走啊. 各种事情之下,人就是懒加心散,好久没写代码 ...
随机推荐
- iOS:文字相关(19-01-08更)
0.写在前面 1.小技巧 UILabel类: 1-1-1).设置行间距富文本,有省略号要求的,需要再次设置省略(初始化时设置的会失效). UITextField类: 1-2-1).清空按钮. UITe ...
- 在angular7中创建组件/自定义指令/管道
在angular7中创建组件/自定义指令/管道 组件 使用命令创建组件 创建组件的命令:ng generate component 组件名 生成的组件组成: 组件名.html .组件名.ts.组件名. ...
- CentOS7.6离线安装JDK1.8
卸载CentOS自带的openJDK: 查看openJDK命令:rpm -qa|grep java 结果: java-1.8.0-openjdk-headless-1.8.0.181-7.b13.el ...
- 《Redis设计与实现》- 数据库
1. 服务器中数据库结构 Redis 服务器将所有数据库都保存在服务器状态 redisServer 结构的 db 数组中,由 redisDb 结构代表一个数据库 struct redisServer ...
- javascript node节点学习
node节点学习 1 . 获取节点(元素)的方法 document.getElementById(); document.getElementsByTagName() document.getElem ...
- 使用Selenium慢慢向下滚动页面
我正试图从航班搜索页面抓取一些数据. 此页面以这种方式工作: 你填写一个表格,然后你点击按钮搜索 – 这没关系.当您单击该按钮时,您将被重定向到包含结果的页面,这就是问题所在.这个页面连续添加结果,例 ...
- tensorflow 模型权重导出
tensorflow在保存权重模型时多使用tf.train.Saver().save 函数进行权重保存,保存的ckpt文件无法直接打开,不利于将模型权重导入到其他框架使用(如Caffe.Keras等) ...
- #20155319 2016-2017-2 《Java程序设计》第3周学习总结
20155319 2016-2017-2 <Java程序设计>第3周学习总结 教材学习内容总结 第三周的学习量还是很大的,需要学习的内容更难了而且 量也变多了,所以投入了更多的时间到Jav ...
- 20155331 ch02 课下作业
2.96 遵循位级浮点编码规则,实现具有如下原型的函数: /* *Compute (int)f. *If conversion cause overflow or f is NaN, return 0 ...
- Hadoop守护进程的作用(转)
概述: <ignore_js_op> Hadoop是一个能够对大量数据进行分布式处理的软件框架,实现了Google的MapReduce编程模型和框架,能够把应用程序分割成许多的 小的工作单 ...