• 题解 P4782 【【模板】2-SAT 问题】


    (n) 个布尔变量 (x_1) (sim x_n) ,另有 (m) 个需要满足的条件,每个条件的形式都是 「(x_i)true / false(x_j) 为 true / false」。比如 「(x_1) 为真或 (x_3) 为假」、「(x_7) 为假或 (x_2) 为假」。

    2-SAT 问题的目标是给每个变量赋值使得所有条件得到满足。

    前置知识:

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    const int MAXN=3e6+10;
    int n,m,a,b,a1,b1,dfn[MAXN],low[MAXN],tot,s[MAXN],sp,sccnum[MAXN],scccnt;
    vector<int>E[MAXN];
    void tarjan(int u){
    	s[sp++]=u;
    	dfn[u]=low[u]=++tot;
    	for(auto v:E[u])
    		if(!dfn[v]){
    			tarjan(v);
    			low[u]=min(low[u],low[v]);
    		}else if(!sccnum[v]){
    			low[u]=min(low[u],dfn[v]);
    		}
    	if(dfn[u]==low[u]){
    		scccnt++;
    		do{
    			sccnum[s[--sp]]=scccnt;
    		}while(s[sp]!=u);
    	}
    }
    int main(){
    	read(n);read(m);
    	for(int i=1;i<=m;i++){
    		read(a);read(a1);read(b);read(b1);
            E[a+(a1^1)*n].push_back(b+b1*n);
            E[b+(b1^1)*n].push_back(a+a1*n);
    	}
    	for(int i=1;i<=(n<<1);i++)
    		if(!dfn[i])tarjan(i);
    	for(int i=1;i<=(n<<1);i++)
    		if(sccnum[i]==sccnum[i+n])return puts("IMPOSSIBLE"),0;
    	puts("POSSIBLE");
    	for(int i=1;i<=n;i++)cout<<(sccnum[i]>sccnum[i+n])<<" ";
    	return 0;
    }
    /*
    3 1
    1 1 3 0
    */
    
  • 相关阅读:
    HashMap
    Linux安装JDK步骤
    CentOS修改Tomcat端口号
    centos 如何关闭防火墙?
    redhat linux/CentOS 6/7 如何关闭防火墙?
    CentOS6.7 常用操作命令
    java 表现层:jsp、freemarker、velocity
    存储的瓶颈(1)
    Monkey测试:启动adb shell失败
    HTTP学习记录:四、头信息(请求和响应)
  • 原文地址:https://www.cnblogs.com/zhaohaikun/p/13830055.html
Copyright © 2020-2023  润新知