【NOI2017】游戏 题解(2-SAT+缩点)
题目大意:有四种场地$a,b,c,x$和三种赛车$A,B,C$,$a$不能跑$A$,$b$不能跑$B$,$c$不能跑$C$,$x$都可以跑。给定$n$个场地和$m$个四元组$(i,h_i,j,h_j)$,意为如果在第$i$个场地跑$h_i$,那么第$j$个场地必须跑$h_j$。输出一种合法方案。若无输出$-1$。
----------------------------------
此题难在建图。把建图搞定就是一个裸的2-SAT板子。
我们规定$0$为每种场地的第一种能跑的车(按字典序),$1$表示第二种能跑的车。对于约束条件,我们有$3$种情况:
1.$h_i$类型的车与$i$冲突,那么我们直接跳过,不用管它。
2.$h_j$类型的车与$j$冲突,那么我们让$i$向$i'$连边,表示如果选择$h_i$则无解。
3.没有冲突情况。那么我们直接按照2-SAT建图方式建就好,即$i$向$j$连边,$j'$向$i'$连边。
对于$x$,我们只要把它当作某一种特定的场地,然后$dfs$枚举所有情况就好。把它当作任意两种场地就可以包含所有可能情况。
时间复杂度$O(2^dn)$。
PS:一开始我超级傻逼,写了一串$if$来判各种情况还各种出锅;后面突然想到只要写个函数判断就行了草。从早上7点来学校写,一直到上午10点才过……
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
int dfn[maxn],low[maxn],vis[maxn],pos[maxn],jishu,tot;
stack<int> st;
int head[maxn],cnt,n,m,d;
int query[maxn][];
char ch[maxn][],c[maxn],s[maxn];
struct node
{
int next,to;
}edge[maxn];
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if (ch=='-') f=-;ch=getchar();}
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void add(int from,int to)
{
edge[++cnt].next=head[from];
edge[cnt].to=to;
head[from]=cnt;
}
inline void clear()
{
jishu=tot=cnt=;
memset(head,,sizeof(head));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(pos,,sizeof(pos));
while(!st.empty()) st.pop();
}
inline void tarjan(int now)
{
dfn[now]=low[now]=++jishu;
st.push(now);vis[now]=;
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
if (!dfn[to]) tarjan(to),low[now]=min(low[now],low[to]);
else if (vis[to]) low[now]=min(low[now],dfn[to]);
}
if (low[now]==dfn[now])
{
tot++;
while(st.top()!=now)
{
int x=st.top();st.pop();
vis[x]=;
pos[x]=tot;
}
int x=st.top();st.pop();
vis[x]=;
pos[x]=tot;
}
}
inline bool check(int pos,char x)
{
if (x+==s[pos]) return ;
return ;
}
inline bool get(int pos,char x)
{
if (s[pos]=='a') return x=='B'?:;
else return x=='A'?:;
}
inline void dfs(int now)
{
if (now>n)
{
clear();
for (int i=;i<=m;i++)
{
int a=query[i][],b=query[i][];
if (check(a,ch[i][])) continue;
if (check(b,ch[i][]))
{
int flag=get(a,ch[i][]);
if (!flag) add(a,a+n);
else add(a+n,a);
continue;
}
else
{
int x=get(a,ch[i][]),y=get(b,ch[i][]);
if (x==&&y==) add(a,b),add(b+n,a+n);
if (x==&&y==) add(a,b+n),add(b,a+n);
if (x==&&y==) add(a+n,b),add(b+n,a);
if (x==&&y==) add(a+n,b+n),add(b,a);
}
}
for (int i=;i<=*n;i++) if(!dfn[i]) tarjan(i);
for (int i=;i<=n;i++) if (pos[i]==pos[i+n]) return;
for (int i=;i<=n;i++)
{
if (pos[i]<pos[i+n])
{
if (s[i]=='a') printf("B");
else printf("A");
}
else
{
if (s[i]=='c') printf("B");
else printf("C");
}
}
exit();
}
if (c[now]=='a') s[now]='a',dfs(now+);
if (c[now]=='b') s[now]='b',dfs(now+);
if (c[now]=='c') s[now]='c',dfs(now+);
if (c[now]=='x'){s[now]='a',dfs(now+);s[now]='b',dfs(now+);}
}
int main()
{
n=read(),d=read();
cin>>(c+);
m=read();
for (int i=;i<=m;i++)
{
query[i][]=read(),cin>>ch[i][];
query[i][]=read(),cin>>ch[i][];
}
dfs();
printf("-1");
return ;
}
【NOI2017】游戏 题解(2-SAT+缩点)的更多相关文章
- BZOJ4945 & 洛谷3825 & UOJ317:[NOI2017]游戏——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4945 https://www.luogu.org/problemnew/show/P3825 ht ...
- 【BZOJ4945】[Noi2017]游戏 2-SAT
[BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么 ...
- P3825 [NOI2017]游戏
题目 P3825 [NOI2017]游戏 做法 \(x\)地图外的地图好做,模型:\((x,y)\)必须同时选\(x \rightarrow y,y^\prime \rightarrow x^\pri ...
- [Luogu P3825] [NOI2017] 游戏 (2-SAT)
[Luogu P3825] [NOI2017] 游戏 (2-SAT) 题面 题面较长,略 分析 看到这些约束,应该想到这是类似2-SAT的问题.但是x地图很麻烦,因为k-SAT问题在k>2的时候 ...
- [UOJ317]【NOI2017】游戏 题解
题意 小 L 计划进行 \(n\) 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 A.B.C 表示.地图一共有四种,分别用小写字 ...
- 【题解】NOI2017游戏
2-SAT.洛谷P3845 一开始以为——怎么有3个呢?后来发现因为每个地图都有一种车是不能用的,所以就等于每一个地图都有两个适应的车啦. 那么对于x类型的地图呢——只有8个,直接2^8暴力枚举每一种 ...
- 题解 洛谷 P3825 【[NOI2017]游戏】
从题面中四元组\((i,h_i,j,h_j)\)限制选择车子型号,不难想到这题要用\(2-SAT\)解决. 考虑转化为\(2-SAT\)模型,发现除地图\(x\)外,其他地图都只有两种车子型号可以参加 ...
- bzoj3825 NOI2017 游戏
题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行nn 场游戏,每场游戏使用一张地 ...
- NOI2017 [NOI2017]游戏 【2-sat】
题目 题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行nn 场游戏,每场游戏使用 ...
随机推荐
- python使用数组实现链表的策略分析
python实现链表数据结构:数组/节点与引用 使用数组策略: 使用数组存储指向其他对象的引用 数组存储空间过度分配 数组填满后,分配一个更大的数组,将旧数组的内容复制到新数组中 class Arra ...
- 题解:2018级算法第一次上机 C1-pair
题目描述 北航2018级软件学院算法分析与设计第一次上机第三题 样例 实现解释 题目类型: 这类题目其实就是典型的递归分析语句形式的问题,也是编译原理课程中语法分析的重要方法之一. 解决方案: 为了解 ...
- Redis安装与运行讲解
第一步:安装Redis 打开网址:https://github.com/MicrosoftArchive/redis/releases 因为版本比较多,最新版已经是3.2.100,我们选择3.0.50 ...
- scala 数据结构(八 ):-map映射操作
在Scala中可以通过map映射操作来解决: 将集合中的每一个元素通过指定功能(函数)映射(转换)成新的结果集合这里其实就是所谓的将函数作为参数传递给另外一个函数,这是函数式编程的特点 以HashSe ...
- scrapy 基础组件专题(十二):scrapy 模拟登录
1. scrapy有三种方法模拟登陆 1.1直接携带cookies 1.2找url地址,发送post请求存储cookie 1.3找到对应的form表单,自动解析input标签,自动解析post请求的u ...
- web 部署专题(一):Gunicorn运行与配置方法
Gunicorn“绿色独角兽”是一个被广泛使用的高性能的Python WSGI UNIX HTTP服务器,移植自Ruby的独角兽(Unicorn )项目,使用pre-fork worker模式,具有使 ...
- MYSQL 使用基础 - 这么用就对了
这篇文章主要梳理了 SQL 的基础用法,会涉及到以下方面内容: SQL大小写的规范 数据库的类型以及适用场景 SELECT 的执行过程 WHERE 使用规范 MySQL 中常见函数 子查询分类 如何选 ...
- 金三银四,资深HR给面试者的十大建议
一.提前复习好你的专业知识 专业知识是最为重要的一点,拥有了坚实的专业基础,你才能迈向成功的彼岸. 因此,面试之前,一定一定要复习好专业知识.对自己学过的知识,要做一个概括,放在脑海中.茶余饭后,复习 ...
- Ethical Hacking - POST EXPLOITATION(1)
METERPRETER BASICS >help - shows help >background - backgrounds current session >sessions - ...
- CAS底层原理与ABA问题
CAS定义 CAS(Compare And Swap)是一种无锁算法.CAS算法是乐观锁的一种实现.CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当预期值A和内存值V相同时,将内存值V修 ...