前置知识

SET问题的标准定义:在计算机科学中,布尔可满足性问题(有时称为命题可满足性问题,缩写为SATISFIABILITY或SAT)是确定是否存在满足给定布尔公式的解释的问题。(全是废话)

说人话就是,你要给n个变量,n需要给他赋值使它满足给你一些形如(x1为1或x3为0或x4为3)的条件,你必须满足所有条件(满足例子的条件需要x1为1,x3为0,x4为3中至少有一个成立)。

但这个问题并不好解决,一旦变量的取值范围变大时间复杂度将不可估量。所以我们考虑最简单的2-sat问题(1-sat大家都会)

2-SAT思路

1.因为2-sat只有两种取值所以一个变量分为x1和x2两个代表取第一种值和第二种值(以下用0,1代表)

2.对于每一个条件如(x1为1或x2为0)可以引申出两个条件若x1为0则x2一定为0,若x2为1则x1为1,我们将x1为0向x2为0以及x2为1向x1为1连边。

3.将所有条件按上面的方法处理后,做强联通分量,如果同一个变量的两个取值在一个强联通分量则意味从变量的0可以推到1,从1可以推到0,则取任何值都不满足条件。如果不在则可以确定变量取值为拓扑序大的数,因为从取值1推到取值2,取值2推不倒取值1,则选择取值2满足条件。

上图条件(x1为1或x2为0)(x1为0或x3为0)(x1为0或x3为0)

答案为x1为0,x2为0,x3为0(答案不唯一),绿色为一种可能的拓扑序,由绿色的拓扑序可推出上面的答案

例题

P4782 【模板】2-SAT - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

AC代码

#include <bits/stdc++.h>
using namespace std;
const int N=2e6+10;
int n,m,cnt,ys,nxt[2*N],hd[2*N],go[2*N],tot,dfn[2*N],low[2*N],col[2*N],ans[N],top,sta[2*N],vis[2*N];
void add(int x,int y)
{
nxt[++tot]=hd[x];go[tot]=y;hd[x]=tot;
return ;
}
void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
sta[++top]=u;
vis[u]=1;
for(int i=hd[u];i;i=nxt[i])
{
int v=go[i];
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
ys++;
while(sta[top]!=u)
{
col[sta[top]]=ys;
vis[sta[top]]=0;
top--;
}
col[sta[top]]=ys;
vis[sta[top]]=0;
top--;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,az,b,bz;scanf("%d%d%d%d",&a,&az,&b,&bz);
add(a+(az&1)*n,b+(bz^1)*n);//1到n为第i个变量选1,n+1到n+n为第i-n个变量选0
add(b+(bz&1)*n,a+(az^1)*n);//简单的建图法,不懂的自己分情况验证
}
for(int i=1;i<=2*n;i++)
if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++)
{
if(col[i]==col[i+n])//在同一强联通分量中
{
printf("IMPOSSIBLE\n");
return 0;
}
}
printf("POSSIBLE\n");
for(int i=1;i<=n;i++)
{
if(col[i]>col[i+n])printf("0 ");//tarjan的是倒序,所以选小的
else printf("1 ");
}
return 0;
}

P4171 [JSOI2010] 满汉全席 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

几乎是模板题,改输入就行了。

#include <bits/stdc++.h>
using namespace std;
const int N=2e6+10;
int k,n,m,cnt,ys,nxt[2*N],hd[2*N],go[2*N],tot,dfn[2*N],low[2*N],col[2*N],top,sta[2*N],vis[2*N];
void add(int x,int y)
{
nxt[++tot]=hd[x];go[tot]=y;hd[x]=tot;
return ;
}
void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
sta[++top]=u;
vis[u]=1;
for(int i=hd[u];i;i=nxt[i])
{
int v=go[i];
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
ys++;
while(sta[top]!=u)
{
col[sta[top]]=ys;
vis[sta[top]]=0;
top--;
}
col[sta[top]]=ys;
vis[sta[top]]=0;
top--;
}
}
int main()
{
scanf("%d",&k);
while(k--)
{
memset(hd,0,sizeof(hd));
memset(dfn,0,sizeof(dfn));
ys=tot=cnt=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
char aa[5],bb[5];
int a=0,b=0,az,bz;
scanf("%s%s",aa,bb);
int c=1;
while(aa[c]>='0'&&aa[c]<='9')
a=a*10+aa[c]-'0',c++;
c=1;
while(bb[c]>='0'&&bb[c]<='9')
b=b*10+bb[c]-'0',c++;
if(aa[0]=='m')az=0;
else az=1;
if(bb[0]=='m')bz=0;
else bz=1;
add(a+(az&1)*n,b+(bz^1)*n);
add(b+(bz&1)*n,a+(az^1)*n);
}
for(int i=1;i<=2*n;i++)
if(!dfn[i])tarjan(i);
int flag=1;
for(int i=1;i<=n;i++)
{
if(col[i]==col[i+n])
{
flag=0;
printf("BAD\n");
break;
}
}
if(flag)printf("GOOD\n");
}
return 0;
}

2-SET详解的更多相关文章

  1. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  2. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  3. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  4. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  5. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  6. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  7. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  8. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  9. Node.js npm 详解

    一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...

  10. .NET应用和AEAI CAS集成详解

    1 概述 数通畅联某综合SOA集成项目的统一身份认证工作,需要第三方系统配合进行单点登录的配置改造,在项目中有需要进行单点登录配置的.NET应用系统,本文专门记录.NET应用和AEAI CAS的集成过 ...

随机推荐

  1. 【Android】Binder的Oneway拦截

    在某些虚拟化,免安装,打点,环境检测,拦截器等场景,针对Android系统服务接口的拦截是常用的技术方案.通常只是针对正向的接口调用,如果涉及被动的服务回调拦截,则实现起来就有些许麻烦. 说明 由于我 ...

  2. 在Deepin 20.2系统中换源并全新图解安装MySQL数据库

    在Deepin 20.2系统中换源并全新图解安装MySQL数据库 https://www.ywnz.com/linuxysjk/9249.html ubuntu下apt-get彻底卸载mysql 删除 ...

  3. ContextCapture中的模型航拍方法和技巧

    在进行实景建模之前,获取被拍摄物体的照片是很重要的一项工作,因为如果没有按照规则拍摄或者拍摄相片质量不佳,将会直接影响我们后期建模,甚至无法建模. 我们建议使用ContextCapture进行建模,则 ...

  4. 那什么是URL、URI、URN?

    URI Uniform Resource Identifier 统一资源标识符 URL Uniform Resource Locator 统一资源定位符 URN Uniform Resource Na ...

  5. 使用 Python 旋转PDF页面、或调整PDF页面顺序

    在将纸质文档扫描成PDF电子文档时,有时可能会出现页面方向翻转或者页面顺序混乱的情况.为了确保更好地浏览和查看PDF文件,本文将分享一个使用Python来旋转PDF页面或者调整PDF页面顺序的解决方案 ...

  6. C#TMS系统学习(ShippingNotice页面)

    C#TMS系统代码-业务页面ShippingNotice学习 学一个业务页面,ok,领导开完会就被裁掉了,很突然啊,他收拾东西的时候我还以为他要旅游提前请假了,还在寻思为什么回家连自己买的几箱饮料都要 ...

  7. Advanced .Net Debugging 8:线程同步

    一.介绍 这是我的<Advanced .Net Debugging>这个系列的第八篇文章.这篇文章的内容是原书的第二部分的[调试实战]的第六章[同步].我们经常写一些多线程的应用程序,写的 ...

  8. C语言:Hello Word(梦开始的地方)

    #include <stdio.h>//标准输入输出头文件,下面的printf打印的函数包含在这个头文件里面 int main() { printf("Hello Word!&q ...

  9. jQuery——动画加载页面

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script&g ...

  10. WPF开发快速入门【2】WPF的基本特性(Style、Trigger、Template)

    概述 本文描述几个WPF的常用特性,包括:样式.触发器和控件模板. 样式/Style Style就是控件的外观,在XAML中,我们通过修改控件的属性值来设置它的样式,如: <!--直接定义sty ...