• 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;
    }
    
    /*
    */
  • 相关阅读:
    XML基础(二)
    XML基础(一)
    转载:数据库应用开发工具Toad使用笔记
    Oracle数据库获取一行记录中某几个字段的最大值/最小值函数
    设置Android让EditText不自动获取焦点
    android TextView selector点击样式改变
    Jenkins build java app under redhat
    Yum
    git windows
    jenkins redhat installation using war file .
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10225668.html
Copyright © 2020-2023  润新知