• 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) M


    题目大意:给你 m 个式子, 问你最少再添加多少式子能使没有任何一种赋值方式使全部的式子为真。 并且在你给的式子中不能有非。

    思路:根据题目给的m个式子可以建出2-Sat的图, 现在问你最少加多少个边使得2-Sat不成立, 我们可以发现我们给出的式子肯定是 a | a

    的形式, 在题目中没有 ~p | ~q这种形式必定无解, 否则最多增加2式子就能完成, 我们枚举a, 取check如果所有都不行就输出2。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ull unsigned long long
    
    using namespace std;
    
    const int N = 4000 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    int n, m;
    bool flag;
    int scc[N], stk[N], dfn[N], low[N], tot, cnt, idx;
    bool in[N];
    vector<int> G[N];
    
    void tarjan(int u) {
        dfn[u] = low[u] = ++idx;
        stk[++tot] = u, in[u] = true;
        for(int v : G[u]) {
            if(!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
            else if(in[v]) low[u] = min(low[u], dfn[v]);
        }
        if(dfn[u] == low[u]) {
            cnt++;
            while(1) {
                int now = stk[tot--];
                scc[now] = cnt;
                in[now] = false;
                if(now == u) break;
            }
        }
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i++) {
            int u, v; scanf("%d%d", &u, &v);
            if(u < 0 && v < 0) flag = true;
            if(u < 0) u = n - u;
            if(v < 0) v = n - v;
            if(u <= n) G[u+n].push_back(v);
            else G[u-n].push_back(v);
            if(v <= n) G[v+n].push_back(u);
            else G[v-n].push_back(u);
        }
        for(int i = 1; i <= n<<1; i++)
            if(!dfn[i]) tarjan(i);
        for(int i = 1; i <= n; i++)
            if(scc[i] == scc[i+n])
                return puts("0"), 0;
        if(!flag) return puts("-1"), 0;
        for(int i = 1; i <= n; i++, cnt = 0, idx = 0) {
            G[i+n].push_back(i);
            for(int j = 1; j <= n<<1; j++) dfn[j] = 0;
            for(int j = 1; j <= n<<1; j++) if(!dfn[j]) tarjan(j);
            for(int j = 1; j <= n; j++)
                if(scc[j] == scc[j+n])
                    return puts("1"), 0;
            G[i+n].pop_back();
        }
        puts("2");
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    JZOJ 5728. 简单计数|| (容斥+动态规划)
    6638. 【GDOI2020.5.16模拟】Seat (队列)
    JZOJ 5750. 青青草原播种计划 (小性质+线段树)
    JZOJ 5753. 完全二叉树 (可持久化线段树维护hash值)
    JS框架-React.js
    flexbox弹性盒子布局
    压缩js和css文件的原理
    JS判断数据类型的方式
    JS数据类型
    ES6新特性
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10225668.html
Copyright © 2020-2023  润新知