题目链接: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. leyer不写content参数直接传递给子页面数据

    function btnAddClickownfund(){ //获取数据 var actual = $("#actual_capitals").html().trim(); // ...

  2. XML第一次简单入门(Lab分析)

    In this tutorial you will create a well-formed and verified XML file. Consider the XML document belo ...

  3. React项目的最佳实践

    项目代码 从零开始简书项目 ​ 从我第一次接触vue这个框架已经过了快一年的时间,陪伴我从前端小白到前端工程师,前端时间也是使用了 ts+vue这样的组合写代码,明显感觉vue与ts似乎没有产生比较好 ...

  4. HTML5视频播放练习:鼠标经过视频播放,鼠标移除停止播放,再次经过继续播放。

    随着HTML5的广泛应用,在一些网站中,经常看到有些预览的短视频预览,鼠标经过就会播放,移除就会停止播放,再次移进去就会继续播放. 自己也研究着做一个比较简单的类似的练习. 视频可以自己到包图网下载, ...

  5. C# 系统应用之鼠标模拟技术及自动操作鼠标

    游戏程序的操作不外乎两种——键盘输入控制和鼠标输入控制,几乎所有游戏中都使用鼠标来改变角色的位置和方向,本文主要是讲述如何使用C#调用Windows API函数实现鼠标模拟操作的功能.首先通过结合Fi ...

  6. linux-2.6.22.6内核启动分析之Makefile文件

    学习目标 分析Makefile文件,了解内核中的哪些文件被编译,如何被编译,连接时顺序如何确定! Linux内核源码中包含很多的Makefile文件,这些Makefile文件又包含其它的一些文件,比如 ...

  7. svn文件管理

    将VS2010工程提交给Git管理时需要哪些文件:    *.h  *.cpp  *.sln  *.vcxproj  *.vcxproj.filters  *.qrc以及Resources目录下的资源 ...

  8. The Road to learn React书籍学习笔记(第二章)

    The Road to learn React书籍学习笔记(第二章) 组件的内部状态 组件的内部状态也称为局部状态,允许保存.修改和删除在组件内部的属性,使用ES6类组件可以在构造函数中初始化组件的状 ...

  9. Oracle入门第五天(下)——数据库其他对象

    一.概述 其他数据库对象 主要掌握的为序列 二.序列 1.什么是序列 序列: 可供多个用户用来产生唯一数值的数据库对象 自动提供唯一的数值 共享对象 主要用于提供主键值 将序列值装入内存可以提高访问效 ...

  10. Hadoop学习总结之Map-Reduce的过程解析

    一.客户端 Map-Reduce的过程首先是由客户端提交一个任务开始的. 提交任务主要是通过JobClient.runJob(JobConf)静态函数实现的: public static Runnin ...