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

    按字典序输出 直接dfs就好了(hdu1814(抄自 http://www.cnblogs.com/kuangbin/archive/2012/10/05/2712429.html)

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAXN = 20020;
    const int MAXM = 100010;
    
    struct Edge {
        int to, next;
    } edge[MAXM];
    int head[MAXN], cntE;
    
    void init() {
        cntE = 0;
        memset(head, -1, sizeof head);
    }
    
    void addedge(int u, int v) {
        edge[cntE].to = v;
        edge[cntE].next = head[u];
        head[u] =cntE++;
    }
    
    bool vis[MAXN];
    int stk[MAXN], top;
    bool dfs(int u) {
        if (vis[u^1]) return false;
        if (vis[u]) return true;
        vis[u] = true; stk[top++] = u;
        for (int i = head[u]; ~i; i = edge[i].next) {
            if (!dfs(edge[i].to)) return false;
        }
        return true;
    }
    
    bool sat(int n) {
        memset(vis, false, sizeof vis);
        for (int i = 0; i < n; ++i) {
            if (vis[i] || vis[i ^ 1]) continue;
            top = 0;
            if (!dfs(i)) {
                while (top) vis[stk[--top]] = false;
                if (!dfs(i^1)) return false;
            }
        }
        return true;
    }
    
    int main() {
        int n, m;
        int u, v;
        while (~scanf("%d%d", &n, &m)) {
            init();
            while (m--) {
                scanf("%d%d", &u, &v);
                u--, v--;
                addedge(u, v^1); //选u就必须选择v^1
                addedge(v, u^1);
            }
            n *= 2;
            if (sat(n)) {
                for (int i = 0; i < n; ++i) {
                    if (vis[i]) printf("%d
    ", i+1);
                }
            } else {
                printf("NIE
    ");
            }
        }
        return 0;
    }

    输出任意一组解

    const int N = 1010;
    const int M = 100010;
    
    struct Edge {
        int from, to, next;
    } edge[M], edge2[M];
    int head[N];
    int cntE, cntE2;
    void addedge(int u, int v) {
        edge[cntE].from = u; edge[cntE].to = v; edge[cntE].next = head[u]; head[u] = cntE++;
    }
    void addedge2(int u, int v) {
        edge2[cntE2].from = u; edge2[cntE2].to = v; edge2[cntE2].next = head[u]; head[u] = cntE2++;
    }
    
    int dfn[N], low[N], idx;
    int stk[N], top;
    int in[N];
    int kind[N], cnt;
    
    void tarjan(int u)
    {
        dfn[u] = low[u] = ++idx;
        in[u] = true;
        stk[++top] = u;
        for (int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].to;
            if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
            else if (in[v]) low[u] = min(low[u], dfn[v]);
        }
        if (low[u] == dfn[u]) {
            ++cnt;
            while (1) {
                int v = stk[top--]; kind[v] = cnt; in[v] = false;
                if (v == u) break;
            }
        }
    }
    
    int opp[N], ind[N], col[N]; // 相对的点 入度 染色 col[]=1选择
    
    bool topsort(int n) // 序号从0开始
    {
        for (int i = 0; i < 2*n; i += 2) {
            int k1 = kind[i]; int k2 = kind[i^1]; // 相对的两个点
            if (k1 == k2) return false;
            opp[k1] = k2; opp[k2] = k1;
        }
        memset(head, -1, sizeof head);
        int u, v;
        for (int i = 0; i < cntE; ++i) {
            u = edge[i].from, v = edge[i].to;
            if (kind[u] != kind[v]) { // 反向建图
                addedge2(kind[v], kind[u]);
                ind[kind[u]]++;
            }
        }
        queue<int> q;
        for (int i = 1; i <= cnt; ++i) if (!ind[i]) q.push(i);
        while (q.size()) {
            u = q.front(); q.pop();
            if (!col[u]) col[u] = 1, col[ opp[u] ] = -1;
            for (int i = head[u]; i != -1; i = edge2[i].next)
                if (--ind[edge2[i].to] == 0) q.push(edge2[i].to);
        }
        return true;
    }
    
    void init() {
        cntE = cntE2 = 0;
        memset(head, -1, sizeof head);
        memset(dfn, 0, sizeof dfn);
        memset(in, false, sizeof in);
        idx = top = cnt = 0;
        memset(ind, 0, sizeof ind);
        memset(col, 0, sizeof col);
    }
  • 相关阅读:
    自动释放池
    图片裁剪成圆形(无边框)
    根据数字对应星期几
    IOS 周几转化数字
    计算两个日期之间的天数
    java——IO流整理(一)
    java——File类的用法整理
    java——用递归和IO流来实现文件的复制
    java——java集合详解
    java——对象的克隆
  • 原文地址:https://www.cnblogs.com/wenruo/p/5884786.html
Copyright © 2011-2022 走看看