[模板] 2-SAT
昨天早上在准备省队集训,发现自己连2-SAT是什么都不知道,于是一早上都投身于2-SAT模板中,终于有个结果。
思路如下:
1.根据条件表达式建边;
2.缩环;
3.判断是否可行;
4.根据缩完环的图反向建边;
5.拓扑排序进行染色(1表示true,2表示false)。
时间复杂度:O(n+m)
/*假设输入是无空格无括号的的c++条件表达式且未知数用编号代替*/
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define L 11
#define N 100001
#define M 1000001
using namespace std;
struct graph{
int nxt,to;
}e[M],gra[M];
int sol[N],col[N];
int f[N],dfn[N],low[N],sta[N];
int g[N],go[N],to[N],n,m,nn,cnt;
bool ins[N];char c[L];queue<int> q;
inline addedge(int x,int y){
e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
}
inline adde(int x,int y){
gra[++cnt].nxt=go[x];go[x]=cnt;gra[cnt].to=y;
}
inline void type(){
int l=strlen(c),i=,x=,y=;
bool flag1=true,flag2=true;
if(c[i]=='!'){
flag1=false;i++;
}
while(i<l&&c[i]>=''&&c[i]<='')
x=x*+c[i++]-'';
if(i==l){
if(flag1) addedge(x+n,x);
else addedge(x,x+n);
return;
}
char cha=c[i];i++;
if(c[i]=='!'){
flag2=false;i++;
}
while(i<l&&c[i]>=''&&c[i]<='')
y=y*+c[i++]-'';
if(cha=='&'){
if(flag1&&flag2){
addedge(x+n,x);
addedge(y+n,y);
}
else if(flag1){
addedge(x+n,x);
addedge(y,y+n);
}
else if(flag2){
addedge(x,x+n);
addedge(y+n,y);
}
else{
addedge(x,x+n);
addedge(y,y+n);
}
}
else if(cha=='|'){
if(flag1&&flag2){
addedge(x+n,y);
addedge(x,y+n);
}
else if(flag1){
addedge(x+n,y+n);
addedge(y,x);
}
else if(flag2){
addedge(x,y);
addedge(y+n,x+n);
}
else{
addedge(x,y+n);
addedge(y,x+n);
}
}
else if(cha=='^'){
if(flag1&&flag2){
addedge(x,y+n);
addedge(x+n,y);
addedge(y,x+n);
addedge(y+n,x);
}
else if(flag1){
addedge(x,y);
addedge(x+n,y+n);
addedge(y,x);
addedge(y+n,x+n);
}
else if(flag2){
addedge(x,y);
addedge(x+n,y+n);
addedge(y,x);
addedge(y+n,x+n);
}
else{
addedge(x,y+n);
addedge(x+n,y);
addedge(y,x+n);
addedge(y+n,x);
}
}
}
inline void tarjan(int u){
dfn[u]=low[u]=++cnt;
sta[++sta[]]=u;ins[u]=true;
for(int i=g[u];i;i=e[i].nxt)
if(!dfn[e[i].to]){
tarjan(e[i].to);
low[u]=min(low[u],low[e[i].to]);
}
else if(ins[e[i].to])
low[u]=min(low[u],low[e[i].to]);
if(dfn[u]==low[u]){
while(sta[sta[]+]!=u){
f[sta[sta[]]]=u;
ins[sta[]--]=false;
}
}
}
inline bool chk(){
for(int i=;i<=n;i++)
if(f[i]==f[i+n]) return false;
return true;
}
inline void build(){
cnt=;
for(int i=;i<=nn;i++)
for(int j=g[i];j;j=e[j].nxt){
if(f[i]!=f[e[j].to]){
adde(f[e[j].to],f[i]);to[i]++;
}
}
}
inline void toposort(){
for(int i=;i<=nn;i++)
if(f[i]==i&&!to[i]) q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
if(!col[u]){
col[u]=;col[u+n]=-;
}
for(int i=go[u];i;i=gra[i].nxt)
if(!(--to[gra[i].to]))
q.push(gra[i].to);
}
}
inline void init(){
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
scanf("%s",&c);type();
}
nn=n<<;cnt=;
for(int i=;i<=nn;i++)
if(!dfn[i]) tarjan(i);
if(!chk()){
printf("No solution.\n");
return;
}
build();
toposort();
for(int i=;i<=n;i++)
col[i]=col[f[i]];
for(int i=;i<=n;i++)
if(col[i]>) printf("%d:true\n",i);
else printf("%d:false\n",i);
}
int main(){
freopen("2sat.in","r",stdin);
freopen("2sat.out","w",stdout);
init();
fclose(stdin);
fclose(stdout);
return ;
}
[模板] 2-SAT的更多相关文章
- 2 - sat 模板(自用)
2-sat一个变量两种状态符合条件的状态建边找强连通,两两成立1 - n 为第一状态(n + 1) - (n + n) 为第二状态 例题模板 链接一 POJ 3207 Ikki's Story IV ...
- TwoSAT算法模板
该模板来自大白书 [解释] 给多个语句,每个语句为“ Xi为真(假) 或者 Xj为真(假)” 每个变量和拆成两个点 2*i为假, 2*i+1为真 “Xi为真 或 Xj为真” 等价于 “Xi为假 –& ...
- C++ 模板基础
我们学习使用C++,肯定都要了解模板这个概念.就我自己的理解,模板其实就是为复用而生,模板就是实现代码复用机制的一种工具,它可以实现类型参数化,即把类型定义为参数:进而实现了真正的代码可重用性.模版可 ...
- (模板)poj2947(高斯消元法解同余方程组)
题目链接:https://vjudge.net/problem/POJ-2947 题意:转换题意后就是已知m个同余方程,求n个变量. 思路: 值得学习的是这个模板里消元用到lcm的那一块.注意题目输出 ...
- 虚拟化技术之kvm镜像模板制作工具virt-sysprep
virt-sysprep这个工具来自libguest-tools这个工具包,它能够把kvm虚拟机对应的磁盘文件做成一个模板,后续我们启动虚拟机就可以基于这个镜像模板启动:什么是镜像模板呢?所谓模板就是 ...
- Jade模板引擎让你飞
写在前面:现在jade改名成pug了 一.安装 npm install jade 二.基本使用 1.简单使用 p hello jade! 渲染后: <p>hello jade!</p ...
- ABP入门系列(2)——通过模板创建MAP版本项目
一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...
- CMS模板应用调研问卷
截止目前,已经有数十家网站与我们合作,进行了MIP化改造,在搜索结果页也能看到"闪电标"的出现.除了改造方面的问题,MIP项目组被问到最多的就是:我用了wordpress,我用了织 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- 【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送
微信支付之微信模板消息推送 今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...
随机推荐
- 004商城项目:ssm框架的整合之后的调试
我们来做一个测试应用,去数据库中输入item表的id然后找到里面的信息转换成json显示在页面上. item表如下: 效果: 代码如下: Dao层: 逆向工程自己的的Mapper. Service层: ...
- QT 对话框二
QMessageBox类 information()函数,主要是提示功能,不需要用户选择 StandardButton QMessageBox::information ( QWidget *pare ...
- C#并行编程中的Parallel.Invoke
一.基础知识 并行编程:并行编程是指软件开发的代码,它能在同一时间执行多个计算任务,提高执行效率和性能一种编程方式,属于多线程编程范畴.所以我们在设计过程中一般会将很多任务划分成若干个互相独立子任务, ...
- crontab小结
crontab是linux下的计划任务,可以用来定时或者按计划运行命令. 创建计划任务: 1.使用crontab -e命令,直接创建计划任务 2.使用编辑器编写好计划任务的文件后,再使用crontab ...
- 关于printf函数的所思所想
缘起大一下学期,C语言程序设计徐小青老师的随口一提,经娄嘉鹏老师提醒,我觉得应该自己整理清楚这一问题.涉及网上资料将会标明出处. 关于printf函数的所思所想 * printf的定义 printf( ...
- Qt学习笔记 线程(一)
Qt中的线程是与平台无关的 QThread 提供了创建一个新线程的方法 新建一个线程,继承QThread并重写它的run()当调用 start()函数时会调用重载的run()函数 例: #ifndef ...
- PRML读书会第九章 Mixture Models and EM(Kmeans,混合高斯模型,Expectation Maximization)
主讲人 网络上的尼采 (新浪微博: @Nietzsche_复杂网络机器学习) 网络上的尼采(813394698) 9:10:56 今天的主要内容有k-means.混合高斯模型. EM算法.对于k-me ...
- Expression Blend4经验分享:自适应布局浅析
今天分享一下Blend制作自适应分辨率布局的经验,大家先看下效果图: 这是一个标准的三分天下的布局,两侧的红色区域是背景区域,是用来干吗的呢,下面简单的分析一下,大家就明白了. 1.拿到一个项目,进行 ...
- 完全开源Android网络框架 — 基于JAVA原生的HTTP框架
HttpNet网络请求框架基于HttpUrlConnection,采用Client + Request + Call的请求模型,支持https默认证书,数字安全证书.支持http代理!后续将会实现队列 ...
- Koa框架实践与中间件原理剖析
最近尝试用了一下Koa,并在此记录一下使用心得. 注意:本文是以读者已经了解Generator和Promise为前提在写的,因为单单Generator和Promise都能够写一篇博文来讲解介绍了,所 ...