模板 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;
原文地址:https://www.cnblogs.com/heimao5027/p/6573865.html