首页 > 其他分享 >2402. 2-SAT 问题

2402. 2-SAT 问题

时间:2022-12-03 22:59:05浏览次数:52  
标签:le int stk 问题 2402 low define SAT

题目链接

2402. 2-SAT 问题

给定 \(n\) 个还未赋值的布尔变量 \(x_1 \sim x_n\)。

现在有 \(m\) 个条件,每个条件的形式为 “\(x_i\) 为 \(0/1\) \(x_j\) 为 \(0/1\) 至少有一项成立”,例如 “\(x_1\) 为 \(1\) 或 \(x_3\) 为 \(0\)”、“\(x_8\) 为 \(0\) 或 \(x_4\) 为 \(0\)” 等。

现在,请你对这 \(n\) 个布尔变量进行赋值(\(0\) 或 \(1\)),使得所有 \(m\) 个条件能够成立。

输入格式

第一行包含两个整数 \(n,m\)。

接下来 \(m\) 行,每行包含四个整数 \(i,a,j,b\),用来描述一个条件,表示 “\(x_i\) 为 \(a\) 或 \(x_j\) 为 \(b\)”。

输出格式

如果问题有解,则第一行输出 POSSIBLE,第二行输出 \(n\) 个整数表示赋值后的 \(n\) 个变量 \(x_1 \sim x_n\) 的值(\(0\) 或 \(1\)),整数之间用单个空格隔开。

如果问题无解,则输出一行 IMPOSSIBLE 即可。

如果答案不唯一,则输出任意一种正确答案即可。

数据范围

\(1 \le n,m \le 10^6\),
\(1 \le i,j \le n\),
\(0 \le a,b \le 1\)

输入样例:

3 2
1 1 3 1
2 0 3 0

输出样例:

POSSIBLE
1 1 0

解题思路

2-SAT

2-SAT 通常解决这样一类问题:给出若干个这样的命题 \(x_1\sim x_n\),给出一些条件 \(x_i\cup x_j\),即 \(x_i\) 或 \(x_j\) 为真,给所有的命题判断真假

首先,有如下等价关系:\(x\cup y\Leftrightarrow \neg x\rightarrow y\Leftrightarrow \neg y\rightarrow x\),

  • 时间复杂度:\(O(n+m)\)

代码

// Problem: 2-SAT 问题
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/2404/
// Memory Limit: 512 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=2e6+5;
int n,m;
int h[N],ne[N],e[N],idx;
int dfn[N],low[N],timestamp,scc_cnt,id[N],stk[N],top;
bool in_stk[N];
void add(int a,int b)
{
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void tarjan(int x)
{
	dfn[x]=low[x]=++timestamp;
	stk[++top]=x,in_stk[x]=true;
	for(int i=h[x];~i;i=ne[i])
	{
		int y=e[i];
		if(!dfn[y])
		{
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(in_stk[y])
			low[x]=min(low[x],dfn[y]);
	}
	if(low[x]==dfn[x])
	{
		int y;
		scc_cnt++;
		do
		{
			y=stk[top--];
			in_stk[y]=false;
			id[y]=scc_cnt;
		}while(y!=x);
	}
}
int main()
{
	memset(h,-1,sizeof h);
    scanf("%d%d",&n,&m);
    while(m--)
    {
    	int i,a,j,b;
    	scanf("%d%d%d%d",&i,&a,&j,&b);
    	i--,j--;
    	add(2*i+!a,2*j+b);
    	add(2*j+!b,2*i+a);
    }
    for(int i=0;i<2*n;i++)
    	if(!dfn[i])tarjan(i);
    for(int i=0;i<n;i++)
    	if(id[i<<1]==id[i<<1|1])
    	{
    		puts("IMPOSSIBLE");
    		return 0;
    	}
    puts("POSSIBLE");
    for(int i=0;i<n;i++)
    	if(id[i<<1]<id[i<<1|1])printf("%d ",0);
    	else
    		printf("%d ",1);
    return 0;
}

标签:le,int,stk,问题,2402,low,define,SAT
From: https://www.cnblogs.com/zyyun/p/16948960.html

相关文章