题目链接: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的更多相关文章

  1. bzoj 4945: [Noi2017]游戏

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

  2. 【刷题】BZOJ 4945 [Noi2017]游戏

    Description http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf Solution 字符串里的'x'看起来很烦,于是考虑枚举这些'x' ...

  3. P3825 [NOI2017]游戏

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

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

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

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

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

  6. BZOJ 4945 UOJ #317 NOI2017 游戏 2-SAT 拓扑排序

    http://uoj.ac/problem/317 https://www.lydsy.com/JudgeOnline/problem.php?id=4945 我现在的程序uoj的额外数据通过不了,b ...

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

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

  8. NOIp 2011 mayan游戏 搜索

    题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  9. POJ3322-经典的游戏搜索问题

    临近毕业真是各种琐事多,好不容易写完几万字蛋疼的论文,又接着户口档案挂靠,毕业旅游,20多个离校盖章,签证被check了几个星期还没消息,希望8月初能走啊. 各种事情之下,人就是懒加心散,好久没写代码 ...

随机推荐

  1. Linux常用命令拾遗

    查看端口对应的程序: netstat -nlap | grep 5004 输出: tcp 0 0 192.168.3.000:5004 192.118.201.00:50800 ESTABLISHED ...

  2. Hive sql & Spark sql笔记

    记录了日常使用时遇到的特殊的查询语句.不断更新- 1. SQL查出内容输出到文件 hive -e "...Hive SQL..." > /tmp/out sparkhive ...

  3. C#串口通信及数据表格存储

    1.开发环境 系统:win10 开发工具:Visual Studio 2017 2.界面设计 串口通信的界面大致如此,在此基础上添加项目所需的调试指令与数据存储功能,界面排布方面可参考其他教程. 3. ...

  4. ubuntu apt源配置

    前言:看见Ubuntu新出了18.04版本感觉不错,装一个玩玩,虽然有很多教程可以参考,但我也给出一个不是很一样的方案吧,尽量解释的详细一点. 为了下载更方便,速度更快,我们往往在使用Linux系列系 ...

  5. Linux IO多路复用 poll

    Linux IO多路复用 poll 之前曾经提到过 select poll 跟select类似,poll改进了select的一个确定,就是poll没有监听上限 不过poll还是需要遍历以及频繁的把数组 ...

  6. PTA(BasicLevel)-1010 一元多项式求导

    一.题目和题意分析 设计函数求一元多项式的导数.x^n [n为整数] 的一阶导数为nx^(n−1). 输入格式: 以指数递降方式输入多项式非零项系数和指数(*绝对值均为不超过 1000 的整数*).数 ...

  7. 一个C语言萌新的学习之旅(持续更新中...)

    三:计算和类型 一:隐式转换和显示转换 隐式转换:隐式转换指的是自动类型转换,自动向精确,大范围类型转换. 显示转换:例如:(int)3.5*6.0f=18.0f (int)(3.5*6.0f)=21 ...

  8. hadoop errors

    1.taskTracker和jobTracker 启动失败 2011-01-05 12:44:42,144 ERROR org.apache.hadoop.mapred.TaskTracker: Ca ...

  9. 20155220 2016-2017-2 《Java程序设计》第八周学习总结

    20155220 2016-2017-2 <Java程序设计>第八周学习总结 教材学习内容总结 第14章 NIO与NIO2 NIO简介 NIO使用频道来衔接数据结点,在处理数据时,NIO可 ...

  10. 20155223 2016-2017-2 《Java程序设计》第10周学习总结

    20155223 2016-2017-2 <Java程序设计>第10周学习总结 教材学习内容总结 Java Socket编程 网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向 ...