题目描述

给出 $n$ 个赛车赛道和A、B、C三种赛车,除了 $d$ 个赛道可以使用所有三种赛车以外每个都只能使用给出的两种之一。另外给出 $m$ 条限制:某个赛道使用X则某另一个赛道必须使用Y。问:是否存在一种方案满足所有条件?输出一种合法方案。

$n\le 50000,d\le 8,m\le 100000$ 。


题解

2-SAT

3-SAT是NP完全问题,由于 $d$ 只有 $8$ ,因此考虑枚举每个万能位置的取值,转化为2-SAT问题。

那么对于一条限制,显然描述对应着一条边;另外一个命题的逆否命题,因此则有:第二个不用Y,第一个就不能用X,还要连这样的边(考场上没有想到对称边,还以为标算不是2-SAT)。

特殊情况:
第一个没有X,则无视这条边;
第二个没有Y,则第一个不能选X,第一个选X向不选X连边。

然后跑tarjan,对立点在同一强连通分量里则不成立,否则有解。缩点建新图跑拓扑排序,对立点中先排到的点不选,后排到的选。

这里有一个小trick:tarjan中强连通分量的编号顺序就是逆拓扑序(考虑tarjan的过程,挺好理解的),因此不用实际拓扑排序,直接比较对立点所属强连通分量编号即可,较小的那个是相应方案。

这样枚举万能位置的选择,每个位置有三种情况。考虑到枚举万能位置不能选什么,一次可以选出两种,只需要枚举两种情况。

时间复杂度 $O(2^dm)$

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
int n , m , flag , px[N] , vx[N] , py[N] , vy[N] , head[N] , to[N << 1] , next[N << 1] , cnt , deep[N] , low[N] , tot , ins[N] , sta[N] , top , bl[N] , num;
char str[N >> 1] , sx[3] , sy[3];
inline void add(int x , int y)
{
to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
inline int getid(int p , int v)
{
if(str[p] == 'a') return v == 0 ? 0 : p * 2 + v - 1;
else if(str[p] == 'b') return v == 1 ? 0 : p * 2 + v / 2;
else return v == 2 ? 0 : p * 2 + v;
}
void tarjan(int x)
{
int i;
deep[x] = low[x] = ++tot , ins[x] = 1 , sta[++top] = x;
for(i = head[x] ; i ; i = next[i])
{
if(!deep[to[i]]) tarjan(to[i]) , low[x] = min(low[x] , low[to[i]]);
else if(ins[to[i]]) low[x] = min(low[x] , deep[to[i]]);
}
if(deep[x] == low[x])
{
int t;
num ++ ;
do
{
t = sta[top -- ];
ins[t] = 0 , bl[t] = num;
}while(t != x);
}
}
void solve()
{
int i , x , y;
memset(head , 0 , sizeof(head));
memset(deep , 0 , sizeof(deep));
cnt = tot = top = num = 0;
for(i = 1 ; i <= m ; i ++ )
{
x = getid(px[i] , vx[i]) , y = getid(py[i] , vy[i]);
if(x)
{
if(y) add(x , y) , add(y ^ 1 , x ^ 1);
else add(x , x ^ 1);
}
}
for(i = 2 ; i <= 2 * n + 1 ; i ++ ) if(!deep[i]) tarjan(i);
for(i = 1 ; i <= n ; i ++ ) if(bl[i << 1] == bl[i << 1 | 1]) return;
flag = 1;
for(i = 1 ; i <= n ; i ++ )
{
if(str[i] == 'a') putchar(bl[i << 1] < bl[i << 1 | 1] ? 'B' : 'C');
else if(str[i] == 'b') putchar(bl[i << 1] < bl[i << 1 | 1] ? 'A' : 'C');
else putchar(bl[i << 1] < bl[i << 1 | 1] ? 'A' : 'B');
}
puts("");
}
void dfs(int x)
{
if(flag) return;
if(x > n)
{
solve();
return;
}
if(str[x] == 'x') str[x] = 'a' , dfs(x + 1) , str[x] = 'b';
dfs(x + 1);
}
int main()
{
int i;
scanf("%d%*d%s%d" , &n , str + 1 , &m);
for(i = 1 ; i <= m ; i ++ ) scanf("%d%s%d%s" , &px[i] , sx , &py[i] , sy) , vx[i] = sx[0] - 'A' , vy[i] = sy[0] - 'A';
dfs(1);
if(!flag) puts("-1");
return 0;
}

【uoj#317】[NOI2017]游戏 2-SAT的更多相关文章

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

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

  2. P3825 [NOI2017]游戏

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

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

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

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

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

  5. bzoj3825 NOI2017 游戏

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

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

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

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

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

  8. Luogu3825 NOI2017 游戏 2-SAT

    传送门 第一眼看上去似乎是一个3-SAT问题 然而\(d \leq 8\)给我们的信息就是:暴力枚举 枚举\(x\)型地图变成\(a\)型地图还是\(b\)型地图(实际上不要枚举\(c\),因为\(a ...

  9. NOI2017 [NOI2017]游戏 【2-sat】

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

随机推荐

  1. 20145226夏艺华 《Java程序设计》实验报告二

    实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步骤 (一)单元测试 ...

  2. Android Sdk Manager更新

    现在Android Sdk Manager无法更新了,什么原因大家都知道,即使使用Goagent效果也不理想. 目前Goagent使用的3.2.2 修改C:\Windows\System32\driv ...

  3. swift3.0通过响应链获取当前试图的控制器

    func parentViewController() -> UIViewController? { let n = next while n != nil { let controller = ...

  4. 【LG3237】[HNOI2014]米特运输

    题面 洛谷 题解 代码 #include <iostream> #include <cstdio> #include <cstdlib> #include < ...

  5. IAR里面STM32工程使用printf

    1. 首先打开工程的options设置 2. 设置编译器的预宏定义,添加宏定义_DLIB_FILE_DESCRIPTOR 3. 修改文件DLib_Defaults.h DLib_Defaults.h ...

  6. equals和==方法比较(一)

    问题描述 今天在使用spotbugs代码走查时发现这样一个问题,两个Long类型的变量使用==判断数值是否相等,spotbugs提示这是一个很致命的错误,代码大概如下, Long l1=123l; L ...

  7. MyBatis.Net 配置

    假设我们现在有这样的需求,要对学生信息进行管理 学生表有要以下要求 字段名称 数据类型 说明 stuNo 字符 学号,该列必填,为主键递增 stuName 字符 学生姓名,该列必填,要考虑姓氏可能是两 ...

  8. .net mvc 使用ueditor的开发(官网没有net版本?)

    1.ueditor的下载导入 官网下载地址:https://ueditor.baidu.com/website/download.html · 介绍 有两种,一种开发版,一种Mini版,分别长这样: ...

  9. hession矩阵的计算与在图像中的应用

    参考的一篇博客,文章地址:https://blog.csdn.net/lwzkiller/article/details/55050275 Hessian Matrix,它有着广泛的应用,如在牛顿方法 ...

  10. Python登录,输入三次密码

    第一段python代码,写了一天,总算不报错了,值得纪念. 基本要求: 写一个登录界面,登录三次锁定用户 1. 包含一个用户信息文件,用户名和密码 2.黑名单文件 过程: 1.先检查是否在黑名单中,如 ...