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;
  • 相关阅读:
    day 66 ORM django 简介
    day 65 HTTP协议 Web框架的原理 服务器程序和应用程序
    jQuery的事件绑定和解绑 事件委托 轮播实现 jQuery的ajax jQuery补充
    background 超链接导航栏案例 定位
    继承性和层叠性 权重 盒模型 padding(内边距) border(边框) margin 标准文档流 块级元素和行内元素
    属性选择器 伪类选择器 伪元素选择器 浮动
    css的导入方式 基础选择器 高级选择器
    03-body标签中相关标签
    Java使用内存映射实现大文件的上传
    正则表达式
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6573865.html
Copyright © 2011-2022 走看看