[模板] 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 微信支付之微信模板消息推送
微信支付之微信模板消息推送 今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...
随机推荐
- Maven私服Nexus3.x环境构建操作记录
Maven介绍Apache Maven是一个创新的软件项目管理和综合工具.Maven提供了一个基于项目对象模型(POM)文件的新概念来管理项目的构建,可以从一个中心资料片管理项目构建,报告和文件.Ma ...
- php常见问题
1,新安装的lamp在打开php文件的时候出现access forbid问题,这个出现的原因是directory的路径权限问题,解决方法 将httpd.conf中的 <Directory /&g ...
- asp.net sql 分页,,优化 排序 及分页,
调用代码: <%@ Register Assembly="AspNetPager" Namespace="Wuqi.Webdiyer" TagPrefix ...
- ORA-28000: the account is locked-的解决办法
ORA-28000: the account is locked第一步:使用PL/SQL,登录名为system,数据库名称不变,选择类型的时候把Normal修改为Sysdba;第二步:选择myjob, ...
- VMware Fusion DHCP方式下如何指定虚拟机IP地址
默认情况下,vmware fusion中的虚拟机,网卡设置成dhcp(动态分配 )时,会分配一个IP地址,但这个IP通常很难记,如果我们想为某台虚拟机挑一个好记的IP地址,可以按如下步骤操作: 命令行 ...
- Chrome扩展开发之二——Chrome扩展中脚本的运行机制和通信方式
目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...
- 从.NET的宠物商店到Android MVC MVP
1 一些闲话 记得刚进公司的时候,我们除了做常规的Training Project外,每天还要上课,接受各种技术培训和公司业务介绍.当时第一次知道QA和SQA的区别.Training Project时 ...
- Android开发遇到的坑(1):Java中List的安全删除问题
在项目的开发过程中,一定少不了的是对Java集合中的List接触.项目中对List的删掉也是一种常见的操作,看上这个操作也没什么好说的样子,但是在项目开发中也是最容易出错的地方,特别是对于新手.有时候 ...
- 创建多个Oracle数据库及相应的实例
转 http://blog.csdn.net/luiseradl/article/details/6972217 对于使用过SQL Server数据库的用户可以会对Oracle中的数据库的实例的概念理 ...
- java用字符写字符
import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.GraphicsEnvir ...