zoukankan      html  css  js  c++  java
  • [洛谷P4782]【模板】2-SAT 问题

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

    题解:$2-SAT$,若$a$推出$b$,就连两条边,分别为$a -> b$和$!b -> !a$,若$a$一定为$true$,就连一条$!a -> a$($false$相同),然后$tarjan$缩点,若一个点的两个状态在同一个强连通分量中,就有矛盾,否则那一个状态先访问到就为什么状态

    卡点:1.$tarjan$缩点弹出栈时条件写错

    C++ Code:

    #include <cstdio>
    #define maxn 1000010 << 1
    using namespace std;
    int n, m;
    int head[maxn], cnt;
    struct Edge {
    	int to, nxt;
    } e[maxn];
    void add(int a, int b) {
    	e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
    }
    int low[maxn], DFN[maxn], stack[maxn], res[maxn], tot, idx, CNT;
    bool vis[maxn];
    inline int min(int a, int b) {return a < b ? a : b;}
    void tarjan(int rt) {
    	DFN[rt] = low[rt] = ++idx;
    	vis[stack[++tot] = rt] = true;
    	int v;
    	for (int i = head[rt]; i; i = e[i].nxt) {
    		v = e[i].to;
    		if (DFN[v]) {
    			if (vis[v]) low[rt] = min(low[rt], DFN[v]);
    		} else {
    			tarjan(v);
    			low[rt] = min(low[rt], low[v]);
    		}
    	}
    	if (DFN[rt] == low[rt]) {
    		CNT++;
    		do {
    			vis[v = stack[tot--]] = false;
    			res[v] = CNT;
    		} while (rt != v);
    	}
    }
    int main() {
    	scanf("%d%d", &n, &m);
    	for (int i = 0; i < m; i++) {
    		int a, b, c, d;
    		scanf("%d%d%d%d", &a, &b, &c, &d);
    		add(a << 1 | !b, c << 1 | d);
    		add(c << 1 | !d, a << 1 | b);
    	}
    	for (int i = 2; i <= (n << 1 | 1); i++) {
    		if (!DFN[i]) tarjan(i);
    	}
    	for (int i = 1; i <= n; i++) {
    		if (res[i << 1] == res[i << 1 | 1]) {
    			puts("IMPOSSIBLE");
    			return 0;
    		}
    	}
    	puts("POSSIBLE");
    	for (int i = 1; i <= n; i++) printf("%d ", res[i << 1] > res[i << 1 | 1]);
    	puts("");
    	return 0;
    }
    

      

  • 相关阅读:
    [Oracle]如何为数据库设置Event(eg: ORA-00235)
    [Oracle]如何为数据库设置Event(eg: ORA-00235)
    C++常用字符串分割方法实例汇总
    C++常用字符串分割方法实例汇总
    C#学习笔记——常量、字段以及事件
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    混淆电路Garbled Circuit介绍
    安全计算实现方法概览
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9432761.html
Copyright © 2011-2022 走看看