zoukankan      html  css  js  c++  java
  • 2-sat

    有 $n$ 个变量和 $m$ 条限制,每条限制是 $x_1$ 为 $True/False$ 或 $x_2$ 为 $True/False$,求构造一组可行方案,或者判断无解

    sol:

    把每个命题拆成原命题和逆否命题,这两个一定等价,要同时满足

    然后对于每个限制 $a,b$ , $a$ 向 $否b$ 连有向边,$b$ 向 $否a$ 连有向边

    然后 Tarjan 缩点,发现同一个强连通分量里的值一定相等,所以如果 $a$ 和 $否a$ 在同一个强连通分量里就是无解

    有解的话可以按 $scc$ 的拓扑序构造一组解,因为 Tarjan 的 $scc$ 标号是拓扑序的逆序,所以每次输出 (id[i]>id[i+n]) 即可

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, s, t) for(register int i = (s), i##end = (t); i <= i##end; ++i)
    #define dwn(i, s, t) for(register int i = (s), i##end = (t); i >= i##end; --i)
    using namespace std;
    inline int read() {
        int x = 0, f = 1; char ch = getchar();
        for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -f;
        for(; isdigit(ch); ch = getchar()) x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 2000010;
    int n, m;
    int first[maxn], to[maxn << 1], nx[maxn << 1], cnt;
    inline void add(int u, int v) {
        to[++cnt] = v;
        nx[cnt] = first[u];
        first[u] = cnt;
    }
    int dfn[maxn], low[maxn], st[maxn], _tim, vis[maxn], top;
    int bl[maxn], scc;
    void Tarjan(int x) {
        low[x] = dfn[x] = ++_tim; st[++top] = x; vis[x] = 1;
        for(int i=first[x];i;i=nx[i]) {
            if(!dfn[to[i]]) {
                Tarjan(to[i]);
                low[x] = min(low[x], low[to[i]]);
            }
            else if(vis[to[i]]) low[x] = min(low[x], dfn[to[i]]);
        }
        if(low[x] == dfn[x]) {
            int now = 0; scc++;
            while(now != x) {
                now = st[top--];
                bl[now] = scc;
                vis[now] = 0;
            }
        }
    }
    int main() {
        n = read(), m = read();
        rep(i, 1, m) {
            int u = read(), a = read(), v = read(), b = read();
            add(v + n * (b ^ 1), u + n * a);
            add(u + n * (a ^ 1), v + n * b);
        } rep(i, 1, n+n) if(!dfn[i]) Tarjan(i);
        rep(i, 1, n) if(bl[i] == bl[i + n]) { puts("IMPOSSIBLE"); return 0; }
        puts("POSSIBLE");
        rep(i, 1, n) cout << (bl[i] > bl[i + n]) << " ";
        cout << endl;
    }
    View Code
  • 相关阅读:
    【深度学习】吴恩达网易公开课练习(class1 week2)
    【深度学习】吴恩达网易公开课练习(class1 week3)
    【python】内存调试
    【python】threadpool的内存占用问题
    Druid: A Real-time Analytical Data Store
    Mesa: GeoReplicated, Near RealTime, Scalable Data Warehousing
    Presto: SQL on Everything
    The Snowflake Elastic Data Warehouse
    Guava 库
    Java Annotation
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10668457.html
Copyright © 2011-2022 走看看