终于搞懂了\(2-sat\)。实际上是个挺简单的东西,像网络流一样关键在于建模。

问题:\(n\)个数\(A\),可以选择\(0\)和\(1\),现在给你\(m\)组条件\(A\),\(B\),对每个条件要求\(A\)为真或者\(B\)为真。

\(2-sat\)的建图方法:把每一个或条件拆成两个。例如对于条件\(A\) \(or\) \(B\):

  • 如果\(A\)为假,那么\(B\)必须为真。(\(A_false\) \(->\) \(B_true\))
  • 如果\(B\)为假,那么\(A\)必须为真。(\(B_false\) \(->\) \(A_true\))

即一条边代表一条指向条件,选择一个点就代表着同时要选择它的闭合子图中的其他点。容易知道:如果存在一个圈,其中同时包含\(x_false\)和\(x_true\),那么取值选择无解。这个过程可以用\(Tarjan\)求\(scc\)来做。

可行解的构造:把原图缩成若干\(scc\)后,对每个条件\(A\),我们优先选对应点拓扑序比较大的那个值,这样就可以向着最容易出解的方向选择。(选择一个点就代表着同时要选择它的闭合子图中的其他点。)

特定解的构造:暴力。此问题\(np\)完全。

#include <bits/stdc++.h>
using namespace std; const int N = 200 + 5;
const int M = 2000 + 5; struct Graph {
int cnt, head[N]; struct Edge {
int nxt, to;
}e[M]; void clear () {
cnt = -1;
memset (head, -1, sizeof (head));
} void add_edge (int u, int v) {
e[++cnt] = (Edge) {head[u], v}; head[u] = cnt;
} stack <int> sta; int _dfn, _sccid; int inq[N], dfn[N], low[N], sccid[N]; void Tarjan (int u) {
dfn[u] = low[u] = ++_dfn;
inq[u] = true; sta.push (u);
for (int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].to;
if (!dfn[v]) {
Tarjan (v);
low[u] = min (low[u], low[v]);
} else if (inq[v]) {
low[u] = min (low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
int tmp; ++_sccid;
do {
tmp = sta.top ();
inq[tmp] = false;
sccid[tmp] = _sccid;
sta.pop ();
}while (tmp != u);
}
} void get_scc (int n) {
_dfn = _sccid = 0;
memset (inq, 0, sizeof (inq));
memset (dfn, 0, sizeof (dfn));
for (int i = 1; i <= n; ++i) {
if (!dfn[i]) Tarjan (i);
}
} }G; int T, n, m; int node (int x, int t) {
return n * t + x;
} int main () {
// freopen ("data.in", "r", stdin);
cin >> T;
while (T--) {
cin >> n >> m; G.clear ();
for (int i = 1; i <= m; ++i) {
static int u, v, t1, t2;
while (!isalpha (t1 = getchar ())); cin >> u;
while (!isalpha (t2 = getchar ())); cin >> v;
t1 = t1 == 'm' ? 0 : 1;
t2 = t2 == 'm' ? 0 : 1;
G.add_edge (node (u, !t1), node (v, t2));
G.add_edge (node (v, !t2), node (u, t1));
}
G.get_scc (n << 1);
bool succ = true;
for (int i = 1; i <= n; ++i) {
if (G.sccid[node (i, 0)] == G.sccid[node (i, 1)]) {
succ = false; break;
}
}
puts (succ ? "GOOD" : "BAD");
}
}

Luogu P4171 [JSOI2010]满汉全席 2-sat的更多相关文章

  1. LUOGU P4171 [JSOI2010]满汉全席

    传送门 解题思路 2-SAT 裸题. 代码 #include<iostream> #include<cstdio> #include<cstring> #inclu ...

  2. 洛谷 P4171 [JSOI2010]满汉全席 解题报告

    P4171 [JSOI2010]满汉全席 题目描述 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中.由于菜色众多而繁杂,只有极少數博学多闻技艺高 ...

  3. 洛谷P4171 [JSOI2010] 满汉全席 [2-SAT,Tarjan]

    题目传送门 满汉全席 题目描述 满汉全席是中国最丰盛的宴客菜肴,有许多种不同的材料透过满族或是汉族的料理方式,呈现在數量繁多的菜色之中.由于菜色众多而繁杂,只有极少數博学多闻技艺高超的厨师能够做出满汉 ...

  4. P4171 [JSOI2010]满汉全席

    简要的学了一下2-sat,然而不会输出方案. 就是个sb模板题啦 // luogu-judger-enable-o2 #include<bits/stdc++.h> #define il ...

  5. [洛谷P4171][JSOI2010]满汉全席

    题目大意:有$n$个点,每个点可以选或不选,有$m$组约束,形如$a,u,b,v$,表示$u=a,v=b$中至少要满足一个条件,问是否存在一组解,多组询问 题解:$2-SAT$,感觉是板子题呀,最后判 ...

  6. P4171 [JSOI2010]满汉全席(2-SAT)

    传送门 2-SAT裸题 把每一道菜拆成两个点分别表示用汉式或满式 连边可以参考板子->这里 然后最尴尬的是我没发现$n<=100$然后化成整数的时候只考虑了$s[1]$结果炸掉了2333 ...

  7. bzoj1823 [JSOI2010]满汉全席(2-SAT)

    1823: [JSOI2010]满汉全席 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1246  Solved: 598[Submit][Status ...

  8. BZOJ 1823: [JSOI2010]满汉全席( 2-sat )

    2-sat...假如一个评委喜好的2样中..其中一样没做, 那另一样就一定要做, 这样去建图..然后跑tarjan. 时间复杂度O((n+m)*K) ------------------------- ...

  9. BZOJ_1823_[JSOI2010]满汉全席_2-sat+tarjan

    BZOJ_1823_[JSOI2010]满汉全席_2-sat 题意:http://www.lydsy.com/JudgeOnline/problem.php?id=1823 分析:一道比较容易看出来的 ...

随机推荐

  1. PYTHON TDD学习(一)-->Python 3.4版本环境安装Django及其启动

    1.安装Python3.4版本,原因:3.4及其以后版本默认自带pip工具,非常好用 2.django 安装命令(c:\Python34\Scripts):pip install django 3.s ...

  2. 【HANA系列】SAP HANA SQL获取某字符串的位置

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL获取某字 ...

  3. Django-MVC框架和MTV框架

    MVC框架 全称Model View Controller,分为三个基本部分:模型Model.视图View和控制器Controller,具有耦合性低.重用性高.生命周期低等优点. 结构 View层,操 ...

  4. 学python的第三天

    函数的作用 不知道大家是否注意到,在上面的代码中,我们做了3次求阶乘,这样的代码实际上就是重复代码.编程大师Martin Fowler先生曾经说过:“代码有很多种坏味道,重复是最坏的一种!”,要写出高 ...

  5. (5.3)mysql高可用系列——mysql复制(理论篇)【续写中】

    关键词:mysql主从复制,mysql复制,MGR,mysql并行复制 目录 [1]mysql支持的复制类型 [2]mysql的主从4种同步方式介绍 (1)异步 (2)同步 (3)5.6 半同步 (4 ...

  6. 水晶报表和rdlc报表传入参数筛选

    在使用报表向客户展示结果数据时,实时的在报表中显示某些特定的数据是必需的,如:显示的部门.打印的日期等.本文只简单的演示向报表内传入一个字符值. 以下是设计好报表之后传入参数的具体操作 一.首先是水晶 ...

  7. 面向对象编程 OOP

    OOP,Object Oriented Programming,原来就是面向对象的编程. 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物. OOD,Object Or ...

  8. SVN简单流程总结

    1   创建仓库 2   启动svn服务器 svnserve -d -r 仓库地址(如:D:\SVN\repoDemo1) 3   新的用户第一次与服务器交互时,需要使用checkout将仓库检出到本 ...

  9. spark教程(七)-文件读取案例

    sparkSession 读取 csv 1. 利用 sparkSession 作为 spark 切入点 2. 读取 单个 csv 和 多个 csv from pyspark.sql import Sp ...

  10. Java Web开发技术教程入门-Model1和Model2

    今天我们聊聊JSP开发中的Model1和Model2. Model1采用了JSP+JavaBean技术开发Web应用.其中,JSP实现页面显示,业务逻辑和流程控制,数据处理由JavaBean完成.在J ...