首页 > 其他分享 >2-SET详解

2-SET详解

时间:2023-11-25 14:23:07浏览次数:31  
标签:SET int top 详解 low x2 x1 取值

前置知识

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;
}

 

标签:SET,int,top,详解,low,x2,x1,取值
From: https://www.cnblogs.com/storms11/p/17855387.html

相关文章

  • 命令行 npm config set legacy-peer-deps true 的作用
    首先,我们需要了解npm,npm是NodePackageManager的缩写,它是Node.js的默认包管理工具。npm提供了许多命令,如install、uninstall、update等,用于管理Node.js的依赖和包。npmconfigsetlegacy-peer-depstrue是npm的一个命令,它主要用于解决npm7在处理peerdepende......
  • Java之API详解之Runtime的详细解析
     3.1概述Runtime表示Java中运行时对象,可以获取到程序运行时设计到的一些信息3.2常见方法常见方法介绍我们要学习的Object类中的常见方法如下所示:publicstaticRuntimegetRuntime() //当前系统的运行环境对象publicvoidexit(intstatus) //停止虚拟机publicintavailab......
  • 【Django基础】操作数据库详解
    djangoORM简介O(objects):类和对象。R(Relation):关系,关系数据库中的表格。M(Mapping):映射。DjangoORM框架的功能:建立模型类和表之间的对应关系,允许我们通过面向对象的方式来操作数据库。根据设计的模型类生成数据库中的表格。通过方便的配置就可以进行数据库的切换。......
  • 写写Redis十大类型zset的常用命令
    其实这些命令官方上都有,而且可读性很强,还有汉化组翻译的http://redis.cn/commands.html,不过光是练习还是容易忘,写一写博客记录一下从zset类型开始写||zset类型适合做排行榜,score排行后显示member应用场景:商品销售的排序zaddkeyscoremember[keymember]//这里和sadd不同的......
  • Jaeger Client Go 链路追踪|入门详解
    目录从何说起Jaeger部署Jaeger从示例了解JaegerClientGo了解trace、spantracer配置Sampler配置Reporter配置分布式系统与span怎么调、怎么传HTTP,跨进程追踪客户端Web服务端Tag、Log和Ref 从何说起之前参加柠檬大佬的训练营(免费白嫖),在大......
  • Java泛型Generics​入门详解
    Java泛型Generics泛型基础知识泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。泛型的格式:<数据类型>注意:泛型只能支持引用数据类型。如果我们没有给集合指定类型,默认认为所有的数据类型都是Object类型,此时可以往集合中添加任意的数据类型。带来一个坏处是由于......
  • Profinet转ModbusTCP网关详解
    Profinet转ModbusTCP网关详解Profinet转ModbusTCP网关是一种常见的工业通信设备,广泛应用于现代工业自动化系统中。通过将Profinet协议转换成ModbusTCP协议,实现了不同网络之间的互联互通。这种网关设备具有简单、可靠的特点,能够满足不同设备之间的数据传递需求。在实际应用中,Prof......
  • 详解CCE服务:一站式告警配置和云原生日志视图
    本文分享自华为云社区《新一代云原生可观测平台之CCE服务日志和告警篇》,作者:云容器大未来。告警和日志是运维人员快速定位问题、恢复异常的主要手段。运维人员日常的工作模式往往是先接收告警信息,再根据告警信息初步判断异常的范围和影响,通过相关组件的日志定位出故障原因,进行系......
  • (转)Git详解
    原文:https://juejin.cn/post/7067165972901134373#heading-0一、什么是版本控制1、什么是版本控制版本控制(Revisioncontrol)是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。实现跨区域多......
  • 六大类型常用函数及详解
    一、数字类型(一)含义概念Python数字数据类型用于存储数值。数据类型是不允许改变的,这就意味着如果改变数字数据类型的值,将重新分配内存空间。以下实例在变量赋值时Number对象将被创建:var1=1var2=10Python支持三种不同的数值类型:整型(int)-通常被称为是整型或整......