• 2sat学习笔记


    介绍

    若干个类似 i or j = 1 的方程组成的方程组,寻找它的可行解的问题,就是2sat问题。方程中未知数个数为n就是n-sat问题。当n大于2时,这个问题是np难问题,因此主要解决的是2-sat问题。

    原理

    对于i or j = 1这个等式,我们可以得到:

    1. i=0 -> j=1
    2. j=0 -> i=1

    这就描述了一种关系。将一个未知量拆成真和假两个状态点,就可以建图了。如果用i代表真,i'代表假,i or j = 1可以表示为:

    1. i' -> j
    2. j' -> i

    求解的方法有两种:dfs和tarjan

    dfs

    选择一个未处理的结点,先选真开始,dfs遍历。如果遍历过程中存在i和i'同时被选到,说明矛盾,换成选假开始。如果还是矛盾,说明无解;否则继续处理剩下结点,直到全部节点都选到,找到一组可行解。

    由于图的对称性,可以保证算法正确性(若存在i->j,必有j'->i')。

    int head[N];
    edge ed[M];
    bool mark[N];
    stack<int> st;
    bool dfs(int p) {
    	if(mark[p ^ 1]) return false;
    	if(mark[p]) return true;
    	mark[p] = true;
    	st.push(p);
    	for(int e = head[p]; e; e = ed[e].ne) {
    		if(!dfs(ed[e].nt)) return false; 
    	}
    	return true;
    }
    
    int main() {
    	bool ok = true;
    	for(int i = 0; i < 2 * m; i += 2) {
    		if(!mark[i] && !mark[i ^ 1]) {
    			while(!st.empty()) st.pop();
    			if(!dfs(i)) {
    				while(!st.empty()) {
    					int cur = st.top();
    					st.pop();
    					mark[cur] = false;
    				}
    				if(!dfs(i ^ 1)) {
    					ok = false;
    					break;
    				}
    			}
    		}
    	}
    	if(ok) cout << "YES" << endl;
    	else cout << "NO" << endl;
    }
    
  • 相关阅读:
    ProtoType Design Tools
    什么是publickeytoken及publickeytoken的作用
    Windows最高权限system帐户
    Q70 AV01本本安装MAC
    解决MDict3在PPC下乱码的问题
    QT_XSP.CPP
    QT_XSP.CPP
    SetupFactory脚本
    DVD IFO FILE HEADER
    SerialPort comstat is being used without defining
  • 原文地址:https://www.cnblogs.com/limil/p/14510959.html
Copyright © 2020-2023  润新知