zoukankan      html  css  js  c++  java
  • HDU

    链接:

    https://vjudge.net/problem/HDU-3062

    题意:

    有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?

    思路:

    2-SAT模板,考虑两个不能同时存在的夫妻,他们的对象可以同时存在,加到边上。
    训练指南的模板
    tarjan模板,
    把所有必需的边连上,缩点,如果某个夫妻再同一个强联通分量内,就不能满足

    代码:

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<vector>
    #include<string.h>
    #include<cstring>
    #include<set>
    #include<queue>
    #include<algorithm>
    #include<math.h>
    #include<stdio.h>
    #include<map>
    #include<stack>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    const int MOD = 20071027;
    const int MAXN = 1e3+10;
    int Next[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};
    
    struct TwoSAT
    {
        int n;
        vector<int> G[MAXN*2];
        bool mark[MAXN*2];
        int S[MAXN*2], c;
    
        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 < (int)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));
        }
    
        void add_clause(int x, int xval, int y, int yval)
        {
            // x = xval or y = 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 < n*2;i += 2)
            {
                if (!mark[i] && !mark[i^1])
                {
                    c = 0;
                    if (!dfs(i))
                    {
                        while(c > 0) mark[S[--c]] = false;
                        if (!dfs(i^1)) return false;
                    }
                }
            }
            return true;
        }
    }sat;
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0), cout.tie(0);
        int n, m;
        while(cin >> n >> m)
        {
            sat.init(n);
            int x1, x2, y1, y2;
            for (int i = 1;i <= m;i++)
            {
                cin >> x1 >> x2 >> y1 >> y2;
                sat.add_clause(x1, y1^1, x2, y2^1);
            }
            if (sat.solve())
                cout << "YES" << endl;
            else
                cout << "NO" << endl;
        }
    
        return 0;
    }
    

    tarjan算法模板

    //tarjan
    //#include<bits/stdc++.h>
    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<vector>
    #include<string.h>
    #include<cstring>
    #include<set>
    #include<queue>
    #include<algorithm>
    #include<math.h>
    #include<stdio.h>
    #include<map>
    #include<stack>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    const int MOD = 20071027;
    const int MAXN = 1e3+10;
    int Next[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};
    
    vector<int> G[MAXN*2];
    stack<int> St;
    int dfn[MAXN*2], low[MAXN*2], sccnum[MAXN*2];
    int dfn_clock, scc_cnt;
    int n, m;
    
    void tarjan(int u)
    {
        dfn[u] = low[u] = ++dfn_clock;
        St.push(u);
        for (int i = 0;i < (int)G[u].size();i++)
        {
            int v = G[u][i];
            if (!dfn[v])
            {
                tarjan(v);
                low[u] = min(low[v], low[u]);
            }
            else if (!sccnum[v])
                low[u] = min(dfn[v], low[u]);
        }
        if (low[u] == dfn[u])
        {
            ++scc_cnt;
            while(true)
            {
                int x = St.top();
                St.pop();
                sccnum[x] = scc_cnt;
                if (x == u)
                    break;
            }
        }
    }
    
    bool solve()
    {
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(sccnum, 0, sizeof(sccnum));
        dfn_clock = scc_cnt = 0;
        for (int i = 0;i < 2*n;i++)
            if (!dfn[i]) tarjan(i);
        for (int i = 0;i < 2*n;i+=2)
            if (sccnum[i] == sccnum[i+1]) return false;
        return 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);
    }
    
    void init()
    {
        for (int i = 0;i < 2*n;i++)
            G[i].clear();
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0), cout.tie(0);
        while(cin >> n >> m)
        {
            init();
            int x1, x2, y1, y2;
            for (int i = 1;i <= m;i++)
            {
                cin >> x1 >> x2 >> y1 >> y2;
                add_edge(x1, y1^1, x2, y2^1);
            }
            if (solve())
                cout << "YES" << endl;
            else
                cout << "NO" << endl;
        }
    
        return 0;
    }
    
  • 相关阅读:
    [洛谷P2711]小行星
    [洛谷P2264]情书
    [洛谷P2626]斐波那契数列(升级版)
    [洛谷P3195][HNOI2008]玩具装箱TOY
    [洛谷P3254]圆桌问题
    [洛谷P1251]餐巾计划问题
    [洛谷P4015]运输问题
    [洛谷P2604][ZJOI2010]网络扩容
    [洛谷P4001][BJOI2006]狼抓兔子
    [洛谷P3153] [CQOI2009]跳舞
  • 原文地址:https://www.cnblogs.com/YDDDD/p/12132790.html
Copyright © 2011-2022 走看看