[模板] 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 微信支付之微信模板消息推送
微信支付之微信模板消息推送 今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...
随机推荐
- jmeter(二)录制脚本
对大多数刚开始接触性能测试的人来说,代码功力可能不是太好,我们可以通过工具,录制脚本来进行测试,以达到我们的目的 一般来讲,录制脚本有两种方法 一.利用badboy进行脚本录制 1.下载安装 badb ...
- 查看Mysql实时执行的Sql语句
最近给客户开发了基于Asp.Net mvc5 +Mysql+EF的项目,但是在EF里无法看到Mysql执行的语句 之前也找到一些监控Mysql的软件但一直没有用起来,现在又遇到了问题即在EF里Mysa ...
- C语言--scanf
关于C语言的scanf,首先看个例子 int get_int(void){ int input; char ch; ){ printf("is not an integer,please e ...
- java script 确认框
<input name="Submit" type="submit" class="inputedit" value="删除 ...
- netcore web.config ConnectionStrings AppSettings
new ConfigurationBuilder().Build().GetSection("ConnectionStrings") new ConfigurationBuilde ...
- 数据库 SQL语法二
聚合函数 -SUM([DISTINCT] FIELDNAME) 求指定列之和,[DISTINCT]选项表示剔除重复记录 例如:SELECT SUM(age) FROM TABLE1; SELECT S ...
- PAT 1067. Sort with Swap(0,*)
1067. Sort with Swap(0,*) (25) Given any permutation of the numbers {0, 1, 2,..., N-1}, it is easy ...
- Eclipse 反编译插件JadClipse安装
下载jadClipse地址: 链接: http://pan.baidu.com/s/1kTN4TPd 提取码: 3fvd 将net.sf.jadclipse_3.3.0.jar拷贝到eclipse的 ...
- 页面跳转Transfer与Redirect的区别你知道吗?
一 前言 关于页面跳转的方式常用的应该就是,链接跳转,js跳转,Server.Tranfser和Response.Redirect 这几种,可是在Tranfser与Redirect之间用哪种更好(本文 ...
- <实训|第八天>超级管理员管理linux用户行为权限附监控主机状态
作为运维工程师,系统管理员,你最大的权力就是给别人分配权力,而且你还能时时控制着他们,今天就给大家介绍一下关于管理用户这一方面的前前后后. 开班第八天: 主要课程大纲:(下面我将把自己的身份定位成一 ...