[UOJ210]寻找罪犯
2-sat神题。。
告诉是2-sat我也完全想不到正解。
看了看题解其实一步步分析也不算很难
这个题首先是要围绕每个人是否是犯人和每句话是否是真话来思考
首先要明确的是:
1.好人不说谎话
2.说了谎话的只能是坏人
所以我们就知道了一组对称的限制条件:
好人->之前没说过谎话
之前说过谎话->坏人
如何判断一句话是否是谎话?
这个人说的话和事实不相符,这也是一种限制条件
这时我们发现还有一个很重要的条件:哪怕是坏人,也最多只说一句谎话
所以如果当前是谎话,那这个人之前所说的所有话和之后所说的所有话都是真话
所以我们在每个点应该存的是在这个点之前(包括该点)有没有说过谎话
利用上面这些限制,就可以做出这道题啦~
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define M 1000010
using namespace std;
struct point{
int to,next;
}e[M<<];
int n,m,num,cnt,tim,tot,top;
int head[M],dfn[M],low[M],st[M],ans[M],co[M],pre[M];
bool vis[M];
int is_crm(int a,int b) {return a+b*n;}
//0->not
//1->yes
int word(int a,int b) {return (n<<)+a+b*m;}
//0->true
//1->false
void add(int from,int to)
{
e[++num].next=head[from];
e[num].to=to;
head[from]=num;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tim;
st[++top]=x;
vis[x]=true;
for(int i=head[x];i;i=e[i].next)
{
int to=e[i].to;
if(!dfn[to])
{
tarjan(to);
low[x]=min(low[x],low[to]);
}
else if(vis[to]) low[x]=min(low[x],low[to]);
}
if(low[x]==dfn[x])
{
tot++;
while(st[top+]!=x)
{
co[st[top]]=tot;
vis[st[top]]=false;
top--;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) pre[i]=*m+;
for(int i=;i<=m;i++)
{
int x,y,opt; scanf("%d%d%d",&x,&y,&opt);
opt^=;
add(is_crm(y,opt^),word(pre[x],));
//如果事实和他说的不是一回事,那他说的就是假话
//如果这句话是假话,在此之前的所有话皆为真话
add(word(pre[x],),is_crm(y,opt));
//如果这个人之前说过假话了,那么这句话就是真话
//他说这个人是什么就是什么
add(word(i,),is_crm(y,opt));
//如果这句话和之前都是真话,他说这个人是什么就是什么
add(is_crm(y,opt^),word(i,));
//这句话说的是反话,那这句话及之前的所有话中有反话
add(word(i,),word(pre[x],));
//如果这句话及之前的所有话皆为真,那么这句话之前所有话皆为真
add(word(pre[x],),word(i,));
//如果之前有假的,这句话及之前的话也有假的
pre[x]=i;
}
//判断是否是罪犯
for(int i=;i<=n;i++)
{
add(word(pre[i],),is_crm(i,));
add(is_crm(i,),word(pre[i],));
}
for(int i=;i<=(n+m)<<;i++)
if(!dfn[i])
tarjan(i);
for(int i=;i<=n;i++)
{
if(co[i]==co[i+n])
{
printf("Impossible");
return ;
}
else if(co[i]>co[i+n]) ans[++cnt]=i;
}
printf("%d\n",cnt);
for(int i=;i<=cnt;i++) printf("%d ",ans[i]);
return ;
}
[UOJ210]寻找罪犯的更多相关文章
- UOJ#210. 【UER #6】寻找罪犯 2-sat
#210. [UER #6]寻找罪犯 链接:http://uoj.ac/problem/210 想法:2-sat模型.每个人拆点,分别表示为犯人.非犯人.每个句供词拆点,分别表示真话.假话.供词与对应 ...
- uoj #210. 【UER #6】寻找罪犯【2-SAT】
首先最直观的,列一排是罪犯一排不是罪犯,对于一个条件u说v(0是1否)f罪犯,如果u不是,那么vf罪犯:如果u是,枚举他说谎的一条wg罪犯,令w(g^1)罪犯连其他条的vf 但是这样有个电度数方,会炸 ...
- 【UOJ #210】【UER #6】寻找罪犯
题目描述 通过一些不可描述的方式,妹滋滋算出了 51% 的得票率,于是就她就把这个公开给了广大用户 —— UOJ 解散已成定局. 几个小时后,UOJ 创始人伏特跳蚤国王宣布辞职,即日起退出 UOJ 团 ...
- [LOJ6029~6052]雅礼集训 2017 选做
Link 代码可以在loj上看我的提交记录. Day 1 [LOJ6029]市场 对于一次除法操作,若区间内所有数的减少量均相同则可视作区间减法,否则暴力递归下去.显然一个线段树节点只会被暴力递归进去 ...
- Tarjan/2-SAT学习笔记
Tarjan/2-SAT Tags:图论 作业部落 评论地址 Tarjan 用来求割边或者割点,求点双联通分量或者边双联通分量 点双联通分量:两个点之间有两条点不相交的路径 边双联通分量:两个点之间有 ...
- Tarjan&2-SAT 总结
\(Tarjan\)&\(2-SAT\) 标签: 知识点总结 安利XZYXZY ps:里面的部分东西来自\(Anson\)和\(yler\)和\(XZY\) 阅读体验:https://zybu ...
- P4478 [BJWC2018]上学路线
Description 小B 所在的城市的道路构成了一个方形网格,它的西南角为(0,0),东北角为(N,M). 小B 家住在西南角,学校在东北角.现在有T 个路口进行施工,小B 不能通过这些路口.小B ...
- 2-sat问题学习记录
如果你不知道什么是sat问题,请看以下问答. Q:sat问题是什麽?A:首先你有n个布尔变量,然后你有一个关于这n个布尔变量的布尔表达式,问你,如果让你随意给这n个布尔变量赋值,这个布尔表达式能否成立 ...
- TYVJ P1403 [NOIP2010]关押罪犯
TYVJ的编译器总是要搞点岔子出来,上次是double必须用f输出而不能用lf,这次又不知道为何CE 于是去了洛谷P1525测试,AC 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1 ...
随机推荐
- Arcgis for Js之GeometryService实现測量距离和面积
距离和面积的測量时GIS常见的功能.在本节,讲述的是通过GeometryService实现測量面积和距离.先看看实现后的效果: watermark/2/text/aHR0cDovL2Jsb2cuY3N ...
- Linux严格区分大小写
虚拟机上安装了MySQL,使用rpm -qa | grep mysql查询时却未找到安装的mysql,后面才发现Linux严格区分大小写,正确的查询命令应该为rpm -qa | grep MySQL, ...
- MVC结构简介
本文编译自J2EE的相关文档.MVC(Model-View-Controller)应用程序结构被用来分析分布式应用程序的特征.这种抽象结构能有助于将应用程序分割成若干逻辑部件,使程序设计变得更加容易. ...
- SQL查询和编程基础
本文转自http://www.cnblogs.com/Jolinson/p/3552786.html 这里的摘抄来自<Microsoft SQL Server 2008技术内幕:T-SQL语言基 ...
- Codevs (3657括号序列 )
题目链接:传送门 题目大意:中文题,略 题目思路:区间DP 这个题是问需要添加多少个括号使之成为合法括号序列,那么我们可以先求有多少合法的括号匹配,然后用字符串长度减去匹配的括号数就行 状态转移方程主 ...
- 160803、如何在ES6中管理类的私有数据
如何在ES6中管理类的私有数据?本文为你介绍四种方法: 在类的构造函数作用域中处理私有数据成员 遵照命名约定(例如前置下划线)标记私有属性 将私有数据保存在WeakMap中 使用Symbol作为私有属 ...
- pro_update_role_pwd
DELIMITER | drop procedure if exists pro_update_role_pwd; CREATE PROCEDURE pro_update_role_pwd ( cro ...
- visual studio 2017 编译v140 TRACKER : error TRK0005: Failed to locate: "CL.exe". 系统找不到指定的文件
原因可能是vs2017中配置v140 的编译命令路径有问题 解决方案: 用vs2017的在线安装程序,选择修改 进去后选择单个组建,在编译器.生成工具和运行时里面把vc++2015.3…… 打钩的取消 ...
- Learn How To Cross Over The Wall
1.一个proxy的实现 http://blog.codingnow.com/2011/05/xtunnel.html 2.SOCK5 RFC http://www.faqs.org/rfcs/rfc ...
- Sql Server 中 GAM、SGAM、PAM、IAM、DCM 和 BCM 的详解与区别
Sql Server 中 GAM.SGAM.PAM.IAM.DCM 和 BCM 的详解与区别 GAM.SGAM.PAM.IAM.DCM 和 BCM 都是 SQL Server 中用来管理空间分配的 ...