• 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;
    }
    
    /*
    */
  • 相关阅读:
    leetcode211
    leetcode209
    leetcode201
    leetcode1396
    leetcode1395
    leetcode1394
    leetcode1386
    leetcode1387
    leetcode1382
    leetcode1376
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10225668.html
Copyright © 2020-2023  润新知