首页 > 其他分享 >2-SAT

2-SAT

时间:2024-07-30 17:50:19浏览次数:12  
标签:ch neg 个数 add vee SAT

为了方便理解,咱们可以先看一组实例。

今天huge要买水果
lbtl说:
1.我不吃梨(\(\neg a\))
2.我吃苹果(b)
3.我吃草莓(c)
lxyt说:
1.我吃梨(a)
2.我吃苹果(b)
3.我不吃草莓(\(\neg c\))
CTH说:
1.我不吃梨(\(\neg a\))
2.我不吃苹果(\(\neg b\))
3.我不吃草莓(\(\neg c\))
(huge:不吃,滚)

我们不妨根据逻辑运算符给他们设计一下状态
lbtl\((\neg a \vee b \vee c)\)
lxyt\((a \vee b \vee \neg c)\)
CTH\((\neg a \vee \neg b \vee \neg c )\)
而他们同时满足则为
\((\neg a \vee b \vee c) \wedge (a \vee b \vee \neg c) \wedge (\neg a \vee \neg b \vee \neg c )\)

那么很好,我们就需要一个算法来处理这个,2-SAT闪亮登场,那既然它都叫“2”-SAT了,那自然是只有两个限定条件,于是我们把想不想吃草莓这一状态删掉,这样就转化为了了2——SAT类型。

那我们如何去解决2—SAT问题呢?

我们可以想到差分约束,通过建图,在图上进行操作来解决。于是我们就可以用强联通分量来搞它。

那差分约束最困难的地方是连边,2-SAT也是如此。先看一道例题

那我们正常想的连边

点击查看代码
 a=read();x=read();  //第a个数为x或第b个数为y 
        b=read();y=read();
        if(x==0&&y==0)      //"如果第a个数为0或第b个数为0"至少满足其一 
        {
            add(a+n,b);     //a=1则b=0 
            add(b+n,a);     //b=1则a=0 
        }
        if(x==0&&y==1)      //"如果第a个数为0或第b个数为1"至少满足其一 
        {
            add(a+n,b+n);   //a=1则b=1 
            add(b,a);       //b=0则a=0 
        }
        if(x==1&&y==0)      //"如果第a个数为1或第b个数为0"至少满足其一
        {
            add(a,b);       //a=0则b=0 
            add(b+n,a+n);   //b=1则a=1 
        }
        if(x==1&&y==1)      //"如果第a个数为1或第b个数为1"至少满足其一
        {
            add(a,b+n);     //a=0则b=1 
            add(b,a+n);     //b=0则a=1 
        }
关于连边的规律


至于为什么
看看佬的blog

但我们可以利用二进制来简化

点击查看代码
for(int i=1;i<=m;i++)
	{
		int a=read(),va=read(),b=read(),vb=read();
		add(a+n*(va&1),b+n*(vb^1));
		add(b+n*(vb&1),a+n*(va^1));
	}

连完边之后,我们就可以跑tarjan了,但要注意tarjan跑出的是拓扑逆序,最后判断的时候要反过来。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

const int N=3e6;
int n,m;
 

int read()
{
	int f=1,s=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch^48);ch=getchar();}
	return s*f;
}
int h[N],to[N],nxt[N],tot;
void add(int x,int y)
{
	to[++tot]=y;
	nxt[tot]=h[x];
	h[x]=tot;
}

int low[N],dfn[N],dfncnt;
int s[N],in_stack[N],tp;
int scc,sc[N];
void tarjan(int u)
{
	low[u]=dfn[u]=++dfncnt;
	in_stack[u]=1;
	s[++tp]=u;
	for(int i=h[u];i;i=nxt[i])
	{
		int v=to[i];
		if(!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(in_stack[v])
		{
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u])
    {
        scc++;
        
        while(s[tp]!=u)
        {
            sc[s[tp]]=scc;
            in_stack[s[tp]]=0;
            tp--;
        }
        sc[s[tp]]=scc;
        in_stack[s[tp]]=0;
        tp--;
    }
}



int main()
{
	n=read(),m=read();
	for(int i=1;i<=m;i++)
	{
		int a=read(),va=read(),b=read(),vb=read();
		add(a+n*(va&1),b+n*(vb^1));
		add(b+n*(vb&1),a+n*(va^1));
	}
	for(int i=1;i<=n*2;i++) if(!dfn[i]) tarjan(i);
	for(int i=1;i<=n;i++) 
	{
		if(sc[i]==sc[i+n]) 
		{
			puts("IMPOSSIBLE");
			exit(0);
		}
	}
	puts("POSSIBLE");
	for(int i=1;i<=n;i++)
	{
		printf("%d ",sc[i]<sc[i+n]);
	}
}

标签:ch,neg,个数,add,vee,SAT
From: https://www.cnblogs.com/zhengchenxi/p/18333045

相关文章

  • 【笔记】图论:2-sat、连通性、欧拉回路选讲
    [AGC059C]GuessingPermutationforasLongasPossible(2-sat)这个东西十分智障,只需要对于所有\(a,b,c\),如果询问顺序是\((a,b),(b,c),(a,c)\),那么不能\(a<b<c\)或\(a>b>c\)。其它的情况(一条链)你一看发现肯定需要出现上述情况,那么这就是充要条件。你一看你直接对所......
  • C++ 【元编程】检查类型是否具有成员 hasattr
    在python中,可以使用hasattr判断类型是否具有某个成员。在C++中,有的时候我们要写一个模板函数,需要对模板进行一定的限制时。这些限制可能为“该模板函数仅用于拥有某个成员的类型”。在标准<type_traits>中,规定了一些列如is_copy_assignable等模板常量,用于判断是否拥有拷贝构造......
  • 从 OR-Tools 设置 CP-SAT 求解器的 IntVar 值
    我目前正在使用googleOR-toolsCP-SAT求解器来解决规划问题。我使用IntVars作为日期的表示。所有这些IntVar都在字典中。我有一些可以正常工作的约束,但我想强制求解器使大约2/3的Intvars低于400。我尝试使用BoolVars解决问题,但没有成功,我运行了出于如何将2/3......
  • 2-SAT学习笔记
    Part0:前置知识Tarjan求SCCPart1:初识2-SATsat即Satisfiability(可满足性问题),2-set问题指对于一串布尔变量,其只有True和False两种取值,在满足若干个约束条件的前提下,对变量赋值举个栗子:A、B、C去吃早餐小A认为一顿好早餐应该菜品多(a)或味道好(b)小B认为一顿好早餐应......
  • SciTech-Theory-Phenomeon(Process and its Outcomes)->Experience(Sensation+Cogniti
    SciTech-Theory:Objective:Phenomeon:aobjectiveProcessanditsOutcomesSubjective:->Experience:Sensation+Cognition->Concept(Natural+Commonpartofexperiences)->Principle(research+invest)->Interpretations->Definition->Theo......
  • SATA信息传输FIS结构总结
    一、简介FIS是一种用于Host和device之间信息传输的机制,每个FIS的格式都是固定的,并且对应唯一的ID。本文主要介绍常用FIS传输过程和对FIS内容进行详解,通过构造的FIS例子方便大家快速掌握FIS,常用的FISTYPE如下:二、总体介绍2.1详细FIS传输过程当双方都空闲时,都在持续......
  • E. Lomsat gelral
    原题链接题解暴力:遍历所有点为根节点的情况,然后遍历子节点,统计众数,时间复杂度\(O(n^2)\)优化:上面的算法时间复杂度之所以为\(O(n^2)\)是因为算父节点时,子节点又重新算了一遍,所以我们可以在算父节点时,保留一个子树的贡献,然后其他子树的贡献暴力遍历一遍运用重链剖分,每次保留......
  • 2-SAT
    前置芝士:强连通分量。先放一个板子题:2-SAT。我们先考虑拆点,把每个变量\(i\)拆成两个点,\(i\times2\)和\(i\times2+1\),前一个代表这个变量\(i\)取假,后一个代表这个变量\(i\)取真。既然有了点,我们就要考虑连边。例如给一个条件:\(1\)取\(1\)或者\(3\)取\(0\)。我......
  • 2-SAT 问题
    2-SAT问题模型有\(n\)个布尔类型的变量\(x_1,x_2,\ldots,x_n\),有\(m\)条限制形如\(x_i\space[\operatorname{or}/\operatorname{and}]\spacex_j=[1/0]\).求一组符合要求的解。核心问题只需要考虑有没有解。对于每个变量都只有两种取值:\(0/1\),那么把每个变......
  • 解决Landsat 5 TM L2影像在ENVI中打不开的情况
    打开Landsat5TML2影像的MTL文件在ENVI中报错如下:解决方法:打开MTL文件更改两个地方:1.将第一行改为:GROUP=L1_METADATA_FILE;2.L2级的影像已经过校正处理,正确的应该是如下图所示*****_SR_B*.TIF,但是在MTL里面往下拉还有一处地方的各波段名称没有更改过来,将下图红色框内......