• 基础但是很重要的2-sat POJ 3678


    http://poj.org/problem?id=3678

    题目大意:就是给你n个点,m条边,每个点都可以取值为0或者1,边上都会有一个符号op(op=xor or and三种)和一个权值c。然后问你如何选择每个点的值,才能让所有点都满足x[i] op x[j] = c

    思路:

    这题学会了好多东西哇,至少我明白了xor,or,and这些关系如何建图拉

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<algorithm>
    #include<iostream>
    #include<utility>
    #include<stack>
    #include<stdlib.h>
    #include<time.h>
    #include<cmath>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 10000 + 5;
    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;
    int n, m;
    
    int main(){
        while (scanf("%d%d", &n, &m) != EOF){
            char ch[5];
            tar.init(n);
            for (int i = 0; i < m; i++){
                int a, b, c; scanf("%d%d%d%s", &a, &b, &c, ch);
                a = a * 2, b = b * 2;///刚开始都是0
                if (ch[0] == 'A'){
                    if (c == 1){///a
                        tar.add_edge(a ^ 1, a);
                        tar.add_edge(b ^ 1, b);
                    }
                    else {
                        tar.add_edge(a, b ^ 1);
                        tar.add_edge(b, a ^ 1);
                    }
                }
                else if (ch[0] == 'O'){
                    if (c == 1){
                        tar.add_edge(a ^ 1, b);
                        tar.add_edge(b ^ 1, a);
                    }
                    else {
                        tar.add_edge(a, a ^ 1);
                        tar.add_edge(b, b ^ 1);
                    }
                }
                else if (ch[0] == 'X'){
                    if (c == 1){
                        tar.add_edge(a, b ^ 1);
                        tar.add_edge(b ^ 1, a);
                        tar.add_edge(a ^ 1, b);
                        tar.add_edge(b, a ^ 1);
                    }
                    else {
                        tar.add_edge(a, b);
                        tar.add_edge(b, a);
                        tar.add_edge(a ^ 1, b ^ 1);
                        tar.add_edge(b ^ 1, a ^ 1);
                    }
                }
            }
            if (tar.solve()) puts("YES");
            else puts("NO");
        }
        return 0;
    }
    View Code

    具体可以看这个博客:http://www.hankcs.com/program/algorithm/poj-3678-katu-puzzle.html

  • 相关阅读:
    Android笔记之调用系统相机拍照
    Android笔记之RoundedImageView
    Java笔记之public、protected、default和private
    Android笔记之ExpandableListView(悬浮吸顶Demo)
    Android笔记之Fragment中创建ViewModel的正确方式
    Android代号、版本及API级别之间的对应关系
    【Phabricator】教科书一般的Phabricator安装教程(配合官方文档并带有踩坑解决方案)
    【Ansible】记一次技术博客害死人的经历——ansible模板变量注入探究
    【linux杂谈】遇到REMOTE HOST IDENTIFICATION HAS CHANGED怎么办?
    【linux杂谈】在SSH连接中,openssh如何解决'Connection refused'错误?
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6591164.html
Copyright © 2020-2023  润新知