昨天早上在准备省队集训,发现自己连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的更多相关文章

  1. 2 - sat 模板(自用)

    2-sat一个变量两种状态符合条件的状态建边找强连通,两两成立1 - n 为第一状态(n + 1) - (n + n) 为第二状态 例题模板 链接一  POJ 3207 Ikki's Story IV ...

  2. TwoSAT算法模板

    该模板来自大白书 [解释] 给多个语句,每个语句为“ Xi为真(假) 或者 Xj为真(假)” 每个变量和拆成两个点 2*i为假, 2*i+1为真 “Xi为真 或 Xj为真”  等价于 “Xi为假 –& ...

  3. C++ 模板基础

    我们学习使用C++,肯定都要了解模板这个概念.就我自己的理解,模板其实就是为复用而生,模板就是实现代码复用机制的一种工具,它可以实现类型参数化,即把类型定义为参数:进而实现了真正的代码可重用性.模版可 ...

  4. (模板)poj2947(高斯消元法解同余方程组)

    题目链接:https://vjudge.net/problem/POJ-2947 题意:转换题意后就是已知m个同余方程,求n个变量. 思路: 值得学习的是这个模板里消元用到lcm的那一块.注意题目输出 ...

  5. 虚拟化技术之kvm镜像模板制作工具virt-sysprep

    virt-sysprep这个工具来自libguest-tools这个工具包,它能够把kvm虚拟机对应的磁盘文件做成一个模板,后续我们启动虚拟机就可以基于这个镜像模板启动:什么是镜像模板呢?所谓模板就是 ...

  6. Jade模板引擎让你飞

    写在前面:现在jade改名成pug了 一.安装 npm install jade 二.基本使用 1.简单使用 p hello jade! 渲染后: <p>hello jade!</p ...

  7. ABP入门系列(2)——通过模板创建MAP版本项目

    一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...

  8. CMS模板应用调研问卷

    截止目前,已经有数十家网站与我们合作,进行了MIP化改造,在搜索结果页也能看到"闪电标"的出现.除了改造方面的问题,MIP项目组被问到最多的就是:我用了wordpress,我用了织 ...

  9. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  10. 【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送

    微信支付之微信模板消息推送                    今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...

随机推荐

  1. Maven私服Nexus3.x环境构建操作记录

    Maven介绍Apache Maven是一个创新的软件项目管理和综合工具.Maven提供了一个基于项目对象模型(POM)文件的新概念来管理项目的构建,可以从一个中心资料片管理项目构建,报告和文件.Ma ...

  2. php常见问题

    1,新安装的lamp在打开php文件的时候出现access forbid问题,这个出现的原因是directory的路径权限问题,解决方法 将httpd.conf中的 <Directory /&g ...

  3. asp.net sql 分页,,优化 排序 及分页,

    调用代码: <%@ Register Assembly="AspNetPager" Namespace="Wuqi.Webdiyer" TagPrefix ...

  4. ORA-28000: the account is locked-的解决办法

    ORA-28000: the account is locked第一步:使用PL/SQL,登录名为system,数据库名称不变,选择类型的时候把Normal修改为Sysdba;第二步:选择myjob, ...

  5. VMware Fusion DHCP方式下如何指定虚拟机IP地址

    默认情况下,vmware fusion中的虚拟机,网卡设置成dhcp(动态分配 )时,会分配一个IP地址,但这个IP通常很难记,如果我们想为某台虚拟机挑一个好记的IP地址,可以按如下步骤操作: 命令行 ...

  6. Chrome扩展开发之二——Chrome扩展中脚本的运行机制和通信方式

    目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...

  7. 从.NET的宠物商店到Android MVC MVP

    1 一些闲话 记得刚进公司的时候,我们除了做常规的Training Project外,每天还要上课,接受各种技术培训和公司业务介绍.当时第一次知道QA和SQA的区别.Training Project时 ...

  8. Android开发遇到的坑(1):Java中List的安全删除问题

    在项目的开发过程中,一定少不了的是对Java集合中的List接触.项目中对List的删掉也是一种常见的操作,看上这个操作也没什么好说的样子,但是在项目开发中也是最容易出错的地方,特别是对于新手.有时候 ...

  9. 创建多个Oracle数据库及相应的实例

    转 http://blog.csdn.net/luiseradl/article/details/6972217 对于使用过SQL Server数据库的用户可以会对Oracle中的数据库的实例的概念理 ...

  10. java用字符写字符

    import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.GraphicsEnvir ...