2-SAT入门

  大概学了一下2-SAT,写了一道模板和一道USACO

  输出一个方案的话,tarjan缩点后倒着拓扑,染色输出。

  求任何解下选哪个就得枚举每个点dfs来判断选哪个。  

HIT 1917(2-sat模板)

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
const int maxn=16010,inf=1e9;
struct poi{int too,pre,x;}e[maxn*10],e2[maxn*10];
int last[maxn],last2[maxn],dfn[maxn],low[maxn],col[maxn],lack[maxn],ru[maxn],rs[maxn],st[maxn],op[maxn];
int n,m,x,y,z,tot,tot2,tott,top,color,flag;
void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
    while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar();
    k*=f;
}
void add(int x,int y){e[++tot].too=y;e[tot].x=x;e[tot].pre=last[x];last[x]=tot;}
void add2(int x,int y){e2[++tot2].too=y;e2[tot2].x=x;e2[tot2].pre=last2[x];last2[x]=tot2;}
int next(int x){return x&1?x+1:x-1;}
void tarjan(int x)
{
    dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top;
    for(int i=last[x];i;i=e[i].pre)
    if(!dfn[e[i].too])tarjan(e[i].too),low[x]=min(low[x],low[e[i].too]);
    else if(!col[e[i].too])low[x]=min(low[x],dfn[e[i].too]);
    if(dfn[x]==low[x])for(color++;top>=lack[x];top--)col[st[top]]=color;
}
void topsort()
{
    top=0;for(int i=1;i<=color;i++)if(!ru[i])st[++top]=i;
    while(top)
    {
        int now=st[top--];
        if(!rs[now])rs[now]=1,rs[op[now]]=2;
        for(int i=last2[now];i;i=e2[i].pre)
        if(!(--ru[e2[i].too]))st[++top]=e2[i].too;
    }
}
void clr()
{
    color=top=tot=tot2=flag=0;
    memset(col,0,sizeof(col));
    memset(dfn,0,sizeof(dfn));
    memset(ru,0,sizeof(ru));
    memset(rs,0,sizeof(rs));
    memset(lack,0,sizeof(lack));
    memset(last,0,sizeof(last));
    memset(last2,0,sizeof(last2));
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        clr();
        for(int i=1;i<=m;i++)read(x),read(y),add(x,next(y)),add(y,next(x));
        for(int i=1;i<=2*n;i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=n;i++)if(col[i<<1]==col[next(i<<1)]){printf("NIE\n");flag=1;break;}
        else op[col[i<<1]]=col[next(i<<1)],op[col[next(i<<1)]]=col[i<<1];
        if(flag)continue;
        for(int i=1;i<=tot;i++)if(col[e[i].x]!=col[e[i].too])add2(col[e[i].too],col[e[i].x]),ru[col[e[i].x]]++;
        topsort();
        for(int i=1;i<=n;i++)if(rs[col[(i<<1)]]==1)printf("%d\n",i<<1);else printf("%d\n",next(i<<1));
    }
    return 0;
}

bzoj 2199

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
const int maxn=500010;
struct poi{int x,too,pre;}e[maxn],e2[maxn];
int n,m,t,tot,tot2,tott,top,color;
int dfn[maxn],low[maxn],col[maxn],last[maxn],last2[maxn],v[maxn],st[maxn],lack[maxn];
char ans[maxn];
void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
    while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar();
    k*=f;
}
int readd()
{
    int x;read(x);char c=getchar();
    while(c!=‘Y‘&&c!=‘N‘)c=getchar();
    if(c==‘Y‘)return (x<<1)^1;
    return x<<1;
}
void add(int x,int y){e[++tot].too=y;e[tot].x=x;e[tot].pre=last[x];last[x]=tot;}
void add2(int x,int y){e2[++tot2].too=y;e2[tot2].x=x;e2[tot2].pre=last2[x];last2[x]=tot2;}
void dfs(int x)
{
    v[x]=t;
    for(int i=last2[x];i;i=e2[i].pre)
    if(v[e2[i].too]!=t)dfs(e2[i].too);
}
bool check(int x)
{
    t++;dfs(x);
    for(int i=1;i<=n;i++)
    if(v[col[(i<<1)^1]]==t&&v[col[i<<1]]==t)return 0;
    return 1;
}
void tarjan(int x)
{
    dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top;
    for(int i=last[x];i;i=e[i].pre)
    if(!dfn[e[i].too])tarjan(e[i].too),low[x]=min(low[x],low[e[i].too]);
    else if(!col[e[i].too])low[x]=min(low[x],dfn[e[i].too]);
    if(dfn[x]==low[x])for(color++;top>=lack[x];top--)col[st[top]]=color;
}
void dfss(int x)
{
    v[x]=1;
    for(int i=last[x];i;i=e[i].pre)
    if(!v[e[i].too])dfss(e[i].too);
}
int main()
{
    read(n);read(m);
    for(int i=1;i<=m;i++)
    {
        int x=readd(),y=readd();
        add(x^1,y);add(y^1,x);
    }
    for(int i=2;i<=((n<<1)^1);i++)if(!dfn[i])tarjan(i);
    for(int i=1;i<=n;i++)if(col[(i<<1)^1]==col[i<<1]){puts("IMPOSSIBLE");return 0;}
    for(int i=1;i<=tot;i++)if(col[e[i].x]!=col[e[i].too])add2(col[e[i].x],col[e[i].too]);
    for(int i=1;i<=n;i++)
    {
        int x=check(col[(i<<1)^1]),y=check(col[i<<1]);
        if(!(x||y)){puts("IMPOSSIBLE");return 0;}
        else if(x&&y)ans[i]=‘?‘;
        else if(x)ans[i]=‘Y‘;
        else if(y)ans[i]=‘N‘;
    }
    for(int i=1;i<=n;i++)putchar(ans[i]);
}

时间: 2024-08-02 18:16:53

2-SAT入门的相关文章

SAT求解器快速入门

从事组合优化或信息安全方向的研究人员,基于SMT研究,需要快速学习SAT求解器的基本原理和方法.以下是快速入门的几点体会: 1.理清需要——是完备求解器还是不完备求解器 完备求解器 能给出SAT.UNSAT.unknow三种确定的答案,尤其是UNSAT结论能给出证明推导过程,指出导致矛盾的关键路径.   不完备求解器能给出SAT.unknow两种结论.SAT结论给出一组可满足解即完成求解任务.可能会存在其他一组或多组可满足解.如果问题本身不知一组解,那么不同的求解器得出的可满足解可能不同. 2.

spring boot学习总结(一)-- 基础入门 Hello,spring boot!

写在最前 SpringBoot是伴随着Spring4.0诞生的: 从字面理解,Boot是引导的意思,因此SpringBoot帮助开发者快速搭建Spring框架: SpringBoot帮助开发者快速启动一个Web容器: SpringBoot继承了原有Spring框架的优秀基因: SpringBoot简化了使用Spring的过程.  Spring Boot解决哪些问题??? Spring Boot使编码变简单,使配置变简单,使部署变简单,使监控变简单 下面正式开始!!!快速入门!!! 1.构建Mav

Yii2框架RESTful API教程(一) - 快速入门

前不久做一个项目,是用Yii2框架写一套RESTful风格的API,就去查了下<Yii 2.0 权威指南 >,发现上面写得比较简略.所以就在这里写一篇教程贴,希望帮助刚接触Yii2框架RESTful的小伙伴快速入门. 一.目录结构 实现一个简单地RESTful API只需用到三个文件.目录如下: frontend ├─ config │ └ main.php ├─ controllers │ └ BookController.php └─ models └ Book.php 二.配置URL规则

bash入门教程

shell的种类: sh  - Bourne shell csh or tcsh - C shell korn - Korn shell bash - GNU Bourne-Again shell 1.最简单的列子 例子 #!/bin/bash # This is a very simple example echo Hello World echo Hello World 解释: 在 BASH 中 第一行的 "#!" 及后面的 "/bin/bash" 就表明该文件

python数据分析入门学习笔记儿

学习利用python进行数据分析的笔记儿&下星期二内部交流会要讲的内容,一并分享给大家.博主粗心大意,有什么不对的地方欢迎指正~还有许多尚待完善的地方,待我一边学习一边完善~ 前言:各种和数据分析相关python库的介绍(前言1~4摘抄自<利用python进行数据分析>) 1.Numpy: Numpy是python科学计算的基础包,它提供以下功能(不限于此): (1)快速高效的多维数组对象naarray (2)用于对数组执行元素级计算以及直接对数组执行数学运算的函数 (3)用于读写硬盘

Linux 入门学习-LINUX命令行描述及常用命令

Linux基础入门之(常用命令) 1.命令行构成 命令提示符一般有GUI.GLI两种接口 1.1命令行组成:命令提示符.prompt.bash(使用的shell) 1.1.1  提示符格式默认为系统变量设置 使用echo命令输出PS1系统本地变量 [[email protected] testdir]# echo $PS1 [\[email protected]\h \W]\$ 1.1.2  用户登录提示符: $:表示普通用户 #:表示系统用户 pwd 显示当前用户所在目录 [[email pr

161103、Spring Boot 入门

Spring Boot 入门 spring Boot是Spring社区较新的一个项目.该项目的目的是帮助开发者更容易的创建基于Spring的应用程序和服务,让更多人的人更快的对Spring进行入门体验,让Java开发也能够实现Ruby on Rails那样的生产效率.为Spring生态系统提供了一种固定的.约定优于配置风格的框架. Spring Boot具有如下特性: 为基于Spring的开发提供更快的入门体验 开箱即用,没有代码生成,也无需XML配置.同时也可以修改默认值来满足特定的需求. 提

Quartz 入门详解

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的日程序表.Jobs可以做成标准的Java组件或 EJBs.官方网站:http://www.opensymphony.com/quartz 相关Jar:   quartz-all-1.6.0.jar   jta.jar   commons-logging-1.1.jar

30分钟Git命令“从入门到放弃”

git 现在的火爆程度非同一般,它被广泛地用在大型开源项目中,但是初学者非常容易"从入门到放弃",各种命令各种参数,天哪,宝宝要吓哭了.实际上新手并不需要了解所有命令的用途,学习是需要一个循序渐进的过程,你可以从强大的命令开始.这个是给新手或熟悉图形工具的老鸟们看的教程,"从入门到放弃" 一.基本了解 git命令是一些命令行工具的集合,它可以用来跟踪,记录文件的变动.比如你可以进行保存,比对,分析,合并等等.这个过程被称之为版本控制.已经有一系列的版本控制系统,比如

Git 入门 ---- Git 常用命令

本文作为  Git 入门 ---- Git 与 SVN 区别 的续篇,继续介绍 Git 的入门知识 四. Git 安装 OS X 版本: Mac 一般自带不需要安装 Windos 版本: https://git-for-windows.github.io/ Linux 版本: Linux 一般也是自带无需安装 五. 创建新仓库 创建新文件夹,cd 到文件夹,执行命令: git init  用来创建新 git 仓库 六. 提交文件进仓库 在新建好 git 仓库的文件夹里加入 readme.txt