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

    图片来自:http://www.hankcs.com/program/algorithm/poj-3678-katu-puzzle.html

    是蓝书325的2-sat弄下来的模板代码

    lrj老师的代码

    这个可以用来选择字典序最小的

    struct TwoSAT{
        int n;
        vector<int> G[maxn * 2];
        bool mark[maxn * 2];
        int c, s[maxn * 2];///c是表示目前dfs到的个数和已经被标记的集合s
        bool dfs(int x){
            if (mark[x ^ 1]) return false;
            if (mark[x]) return true;
            mark[x] = true;
            s[c++] = x;
            for (int i = 0; i < G[x].size(); i++)
                if (!dfs(G[x][i])) return false;
            return true;
        }
    
        void init(int n){
            this->n = n;
            for (int i = 0; i < 2 * n; i++) G[i].clear();
            memset(mark, 0, sizeof(mark));
        }
        ///利用题目条件找到x和y,即假设x1[0] | x2[1] = false;即:x1[0]|!x2[1]=false
        ///那么我们反转该条件:即x1[1]|!x2[0] = true,即两者任意一个成立即为true
        ///那么我们只要交叉建图即可
        void add_edge(int x, int xval, int y, int yval){
            x = x * 2 + xval, y = y * 2 + yval;
            G[x ^ 1].push_back(y);
            G[y ^ 1].push_back(x);
        }
    
        bool solve(){
            for (int i = 0; i < 2 * n; i += 2){
                if (!mark[i] && !mark[i + 1]){
                    c = 0;
                    if (!dfs(i)){
                        while (c) mark[s[--c]] = false;
                        if (!dfs(i + 1)) return false;
                    }
                }
            }
            return true;
        }
    };
    TwoSAT sat;

    tarjan的,利用强连通的代码

    struct Tarjan{
        int n;
        int pre[maxn*2], low[maxn*2], sccno[maxn*2], dfstime, scc_cnt;
        stack<int> s;
        vector<int> G[maxn*2];
        void init(int n){
            this->n = n;
            for (int i = 0; i <= n * 2; i++) G[i].clear();
            while (!s.empty()) s.pop();
        }
        void add_edge(int x, int y){
            G[x].push_back(y);
        }
        void dfs(int u){
            pre[u] = low[u] = ++dfstime;
            int len = G[u].size();
            s.push(u);
            for (int i = 0; i < len; i++){
                int v = G[u][i];
                if (pre[v] == -1){
                    dfs(v);
                    low[u] = min(low[u], low[v]);
                }
                else if (!sccno[v]){///下面为什么是pre[v]而不是low[v](两者都可以)
                    low[u] = min(low[u], pre[v]);///因为环装最后总会变回来,一样的
                }
            }
            if (low[u] == pre[u]){
                scc_cnt++;
                while (true){
                    int x = s.top(); s.pop();
                    sccno[x] = scc_cnt;
                    if (x == u) break;
                }
            }
            return ;
        }
    
        bool solve(){///看情况修改solve
            memset(pre, -1, sizeof(pre));
            memset(low, 0, sizeof(low));
            memset(sccno, 0, sizeof(sccno));
            dfstime = scc_cnt = 0;
            for (int i = 0; i < 2 * n; i++){
                if (pre[i] == -1) dfs(i);
            }
            for (int i = 0; i < 2 * n; i += 2){///如果两个点在同一个环里面,那么就返回false
                if (sccno[i] == sccno[i + 1]) return false;
            }
            return true;
        }
    };
    Tarjan tar;
  • 相关阅读:
    md5
    表空间
    create_index
    非额度合同和额度合同
    如何在linux中查找python安装包的路径
    Golang中的SingleFlight与CyclicBarrier
    linux安装protoc
    protobuf 的优缺点
    Xshell 连接 VirtualBox
    限制 input 输入框只能输入纯数字
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6573865.html
Copyright © 2011-2022 走看看