zoukankan      html  css  js  c++  java
  • [模板][P4782]2-SAT

    Description:

    有n个布尔变量(x_1)~(x_n),另有m个需要满足的条件,每个条件的形式都是“(x_i)为true/false或(x_j)为true/false”。比如“(x_1)为真或(x_3)为假”、“(x_7)为假或(x_2)为假”。2-SAT 问题的目标是给每个变量赋值使得所有条件得到满足。

    Hint:

    (1le n,mle 10^6)

    Solution:

    模板题,详见代码

    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    using namespace std;
    const int mxn=2e6+5;
    int n,m,tot,cnt,col;
    int hd[mxn],bl[mxn],dfn[mxn],low[mxn],ins[mxn];
    stack<int > st;
    
    struct ed {
    	int to,nxt;
    }t[mxn<<1];
    
    inline void chkmax(int &x,int y) {if(x<y) x=y;}
    inline void chkmin(int &x,int y) {if(x>y) x=y;}
    
    inline void add(int u,int v) {
    	t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
    }
    
    void tj(int u)
    {
    	dfn[u]=low[u]=++tot; st.push(u); ins[u]=1;
    	for(int i=hd[u];i;i=t[i].nxt) {
    		int v=t[i].to;
    		if(!dfn[v]) tj(v),chkmin(low[u],low[v]);
    		else if(ins[v]) chkmin(low[u],dfn[v]);
    	}
    	if(dfn[u]==low[u]) {
    		++col;
    		do{
    			bl[u]=col; u=st.top();
    			st.pop(); ins[u]=0;
    		} while(low[u]!=dfn[u]);
    	}
    } //tarjan基本操作,没什么好说的
    
    int main()
    {
    	scanf("%d%d",&n,&m); int u,v,x,y;
    	for(int i=1;i<=m;++i) {
    		scanf("%d%d%d%d",&u,&x,&v,&y);
    		add(u+n*(x^1),v+n*y);
    		add(v+n*(y^1),u+n*x); //建边,很好懂的
    	}
    	for(int i=1;i<=2*n;++i) 
    		if(!dfn[i]) tj(i);
    	for(int i=1;i<=n;++i) 
    		if(bl[i]==bl[i+n]) {
    			puts("IMPOSSIBLE");
    			return 0;
    		}
    	puts("POSSIBLE");	
    	for(int i=1;i<=n;++i) 
    		printf("%d ",bl[i]>bl[i+n]);	//按较大拓扑序输出答案
        return 0;
    }
    
    
  • 相关阅读:
    树上莫队学习笔记
    点分治学习笔记
    7.11总结
    线段树合并学习笔记
    7.10总结
    bzoj1201: [HNOI2005]数三角形----递推+bitset
    bitset(01串)优化
    Tarjan系列1
    bsgs(Baby Steps Giant Steps)算法
    [SD2015]序列统计——solution
  • 原文地址:https://www.cnblogs.com/list1/p/10460838.html
Copyright © 2011-2022 走看看