[模板]2-SAT 问题&和平委员会
tarjan的运用
this is a problem:link
2-SAT处理的是什么
首先,把「2」和「SAT」拆开。SAT 是 Satisfiability 的缩写,意为可满足性。即一串布尔变量,每个变量只能为真或假。要求对这些变量进行赋值,满足布尔方程。
所以看这道题
若ai为真或aj为真,所以当ai为真时aj必须为假,若aj为真时ai必须为假
所以假设i为ai为真,i+n为ai为假
所以建边(i,j+n),(j,i+n),连接u,v表示选u就要选v
然后用可能出现环,所以用tarjan缩点表示若i,j在同一强联通分量中,那么他们两个必须要选
然后可以想无解情况,若i于i+n都在同一强连通分量中,于是无解,因为他们两个都必须要选,但却不能都选
然后想怎么输出解
因为拓扑序的关系 拓扑序在前的点有可能能够到达拓扑序靠后的点 而靠后的一定无法到达靠前的 因此选择靠后的一定能够保证出合法解 而选择靠前的可能会导致前面的点存在一条通路到达后面的点致使答案出现错误 这样可以感性理解,至于证明利用了建图过程中的对称性。什么意思呢1,就是tarjan为反拓扑顺序,所以说就要选择强连通编号中最大的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
struct node{
int u,v,nex;
}x[];
int n,m,head[],cnt,dfn[],st[],num,top,col,co[],low[],tot;
void tarjan(int xx)
{
low[xx]=dfn[xx]=++num;
st[++tot]=xx;
for(int i=head[xx];i!=-;i=x[i].nex)
{
int v=x[i].v;
if(!dfn[v])
{
tarjan(v);
low[xx]=min(low[xx],low[v]);
}
else if(!co[v]) low[xx]=min(low[xx],dfn[v]);
}
if(dfn[xx]==low[xx])
{
co[xx]=++col;
while(st[tot]!=xx)
{
co[st[tot]]=col;
tot--;
}
tot--;
}
return;
}
void add(int u,int v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int main()
{
memset(head,-,sizeof(head));
n=read(),m=read();
for(int i=;i<=m;i++)
{
int a=read(),xa=read(),b=read(),yb=read();
if(xa==&&yb==) add(a,b+n),add(b,a+n);
if(xa==&&yb==) add(a,b),add(b+n,a+n);
if(xa==&&yb==) add(a+n,b),add(b+n,a);
if(xa==&&yb==) 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(co[i]==co[i+n]){cout<<"IMPOSSIBLE";return ;}
cout<<"POSSIBLE"<<endl;
for(int i=;i<=n;i++)
{
if(co[i]>co[i+n]) cout<<<<" ";
else cout<<<<" ";
}
return ;
}
/*
3 2
1 1 3 0
3 1 1 0
*/
一道2-SAT的例题
和平委员会 |
| link |
|
试题描述
|
|
根据宪法,Byteland 民主共和国的公众和平委员会应该在国会中通过立法程序来创立。 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍。
此委员会必须满足下列条件: 每个党派都在委员会中恰有 1 个代表, 如果 2 个代表彼此厌恶,则他们不能都属于委员会。 每个党在议会中有 2 个代表。代表从 1 编号到 2n。 编号为 2i−1 和 2i 的代表属于第 i 个党派。 任务:写一程序读入党派的数量和关系不友好的代表对,计算决定建立和平委员会是否可能,若行,则列出委员会的成员表。 |
|
输入
|
|
第一行有两个非负整数 n 和 m。他们各自表示:党派的数量 n 和不友好的代表对 m。 接下来 m 行,每行为一对整数 a,b,表示代表 a,b 互相厌恶。
|
|
输出
|
|
如果不能创立委员会,则输出信息NIE。若能够成立,则输出包括 n 个从区间 1 到 2n 选出的整数,按升序写出,每行一个,这些数字为委员会中代表的编号。
如果委员会能以多种方法形成,程序可以只输出它们的某一个。 |
|
输入示例
|
|
3 2
1 3 2 4 |
|
输出示例
|
|
1
4 5 |
|
其他说明
|
|
数据范围与提示
1≤n≤8000,0≤m≤20000,1≤a<b≤2n |
一个2-SAT的板子,就是与上一道题的区别是,上一道题必须二选一,这一次可以两个都不选,所以选择拓扑序小的(想一想,为什么)、
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
int f=,ans=;char c;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
struct node{
int u,v,nex;
}x[];
int n,m,cnt,head[],dfn[],low[],tot,num,st[],co[],col;
void add(int u,int v)
{
x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}
int cx(int s)
{
if(s%==) return s-;
else return s+;
}
void tarjan(int xx)
{
low[xx]=dfn[xx]=++num;
st[++tot]=xx;
for(int i=head[xx];i!=-;i=x[i].nex)
{
int v=x[i].v;
if(!dfn[v])
{
tarjan(v);
low[xx]=min(low[xx],low[v]);
}
else if(!co[v]) low[xx]=min(low[xx],dfn[v]);
}
if(dfn[xx]==low[xx])
{
co[xx]=++col;
while(st[tot]!=xx)
{
co[st[tot]]=col;
tot--;
}
tot--;
}
return;
}
int main()
{
memset(head,-,sizeof(head));
n=read(),m=read();
for(int i=;i<=m;i++)
{
int u=read(),v=read();
add(u,cx(v)),add(v,cx(u));
}
for(int i=;i<=*n;i++)
if(!dfn[i]) tarjan(i);
for(int i=;i<=*n;i=i+)
{
if(co[i]==co[i+])
{
cout<<"NIE";
return ;
}
}
for(int i=;i<=*n;i=i+)
{
if(co[i]>co[i+]) cout<<i+<<endl;
else cout<<i<<endl;
}
return ;
}
[模板]2-SAT 问题&和平委员会的更多相关文章
- HDU 1814 Peaceful Commission / HIT 1917 Peaceful Commission /CJOJ 1288 和平委员会(2-sat模板题)
HDU 1814 Peaceful Commission / HIT 1917 Peaceful Commission /CJOJ 1288 和平委员会(2-sat模板题) Description T ...
- 【POI2001】【HDU1814】和平委员会
题面 Description 根据宪法,Byteland民主共和国的公众和平委员会应该在国会中通过立法程序来创立. 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍. 此委员会必须满足下列条 ...
- COGS:313. [POI2001] 和平委员会
313. [POI2001] 和平委员会 ★★☆ 输入文件:spo.in 输出文件:spo.out 评测插件时间限制:1 s 内存限制:128 MB 题目描述 根据宪法,Bytelan ...
- HDU1814和平委员会
题目大意: 有n对的人,编号从1-2*n,m对的人之间互相不喜欢,每对人中必徐选1个人加入和平委员会,求字典序最小的解 -------------------------------- 2-SAT问题 ...
- [POI2001]和平委员会
题目描述 根据宪法,Byteland民主共和国的公众和平委员会应该在国会中通过立法程序来创立. 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍. 此委员会必须满足下列条件: 每个党派都在委 ...
- LOJ10097和平委员会
POI 2001 根据宪法,Byteland民主共和国的公众和平委员会应该在国会中通过立法程序来创立. 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍. 此委员会必须满足下列条件: 每个党 ...
- cogs 313. [POI2001] 和平委员会(2-SAT
http://cogs.pro:8080/cogs/problem/problem.php?pid=pyzQimjkj 题意:有n个集合,每个集合有俩元素,要从n个中各选一个放一堆,但是有的俩不能同时 ...
- P5782-[POI2001]和平委员会【2-SAT】
正题 题目链接:https://www.luogu.com.cn/problem/P5782 题目大意 \(n\)对人,每对之间恰好有一个人出席.\(m\)对仇恨关系表示两个人不能同时出席. 求是否有 ...
- HIT 1917 2—SAT
题目大意:一国有n个党派,每个党派在议会中都有2个代表, 现要组建和平委员会,要从每个党派在议会的代表中选出1人,一共n人组成和平委员会. 已知有一些代表之间存在仇恨,也就是说他们不能同时被选为和平委 ...
随机推荐
- C语言的函数调用过程(栈帧的创建与销毁)
从汇编的角度解析函数调用过程 看看下面这个简单函数的调用过程: int Add(int x,int y) { ; sum = x + y; return sum; } int main () { ; ...
- selenium自动化之js处理点击事件失效
有时候,元素明明已经找到了,使用click()就是无法触发点击事件(当然,这种情况十分少见,至少我只遇到过一次).下面告诉大家这种场景的解决方案. 使用js代码来点击[博客园]这个按钮 代码: #!/ ...
- JY播放器【喜马拉雅FM电脑端,附带下载功能】
今天给大家带来一款神器----JY播放器.可以不用打开网页就在电脑端听喜马拉雅FM的节目,而且可以直接下载,对于我这种强迫症患者来说真的是神器.我是真的不喜欢电脑任务栏上面密密麻麻的. 目前已经支持平 ...
- 云主机启动提示Booting from Hard Disk GRUB
版本:Openstack ocata 系统:centos7.3 环境:VMware workstation12 解决方法: 或者
- 笔试题:C++打印队列
题目:打印队列 题目介绍:现在用打印机打印队列,已知打印任务有9个优先级(1-9),现在给出一系列任务,求输出打印顺序(任务下标,从0开始). 例: 输入:9,3,5,4,7,1 输出:0,4,2,3 ...
- 微软职位内部推荐-Senior Software Lead-Index Gen
微软近期Open的职位: Position: Senior Software Development Lead Bing Index Generation team is hiring! As one ...
- 亚马逊AWS业务副总裁:如何在基础设施上降成本
腾讯科技 林靖东 11月17日编译 亚马逊Amazon Web Services业务的副总裁.著名工程师詹姆斯汉密尔顿(James Hamilton)在AWS re:Invent大会上解释了公司是如何 ...
- win10 redis安装教程
下载解压,没什么好说的,在解压后的目录下有以下这些文件: 在 命令行 启动服务端 redis目录下执行: redis-server.exe redis.windows.conf 如果需要 开机启动:执 ...
- centos上搭建git服务--2
在 Linux 下搭建 Git 服务器 环境: 服务器 CentOS6.6 + git(version 1.7.1)客户端 Windows10 + git(version 2.8.4.window ...
- php的大小写敏感问题整理
php的大小写敏感问题整理 今天在开发php的过程中,因为命名大小写的问题导致代码错误,所以从网上整理了php的大小写敏感的一些资料,需要的朋友可以参考下. PHP对大小写敏感问题的处理比较乱,写 ...