zoukankan      html  css  js  c++  java
  • hdoj 1824 Let's go home(2-SAT)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1824

    思路分析:该问题为2-SAT问题;需要注意逻辑推理的等价性;

    (1)题目第一个条件:每一个队或者队长留下或者其与两名队员同时留下,或者表明只能为两种情况中的一种;假设三人为A,B,C,队长为A,0表示不留下,1表示留下,因为B与C同时留下或者不留下,只要B,C中其中一个没有留下或者留下,则B,C中另一个也同样留下或者不留下,所以可以从该条件中推导出六条等价关系,即A不留下->B,C同时留下,A留下->B,C同时不留下,B留下->C留下,A不留下,B留下->C留下,A不留下,C留下->B留下,A不留西,C不留下->B不留下,A留下;

    (2)题目中第二个条件:每一对队员,如果队员A留下,则B必须回家休息,或者B留下,A必须回家休息;则可以推导出两条等价式:A留下->B不留下,B留下->A不留下,注意在这个条件中可以A,B都不留下;

    代码如下:

    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    const int MAX_N = 2 * 5000 + 10;
    struct TwoSAT {
        int n;
        vector<int> G[2 * MAX_N];
        bool mark[2 * MAX_N];
        int S[2 * MAX_N], c;
    
        void Init(int n)
        {
            this->n = n;
            for (int i = 0; i <= 2 * n; ++i)
                G[i].clear();
            memset(mark, 0, sizeof(mark));
        }
    
        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 < G[x].size(); ++i)
            {
                if (!Dfs(G[x][i]))
                    return false;
            }
            return true;
        }
    
        void AddClause(int x, int y)
        {
            int a = 2 * x;
            int b = 2 * y;
            G[a ^ 1].push_back(b);
            G[b ^ 1].push_back(a);
        }
    
        void AddClauseTeam(int i, int j, int k)
        {
            int a = 2 * i;
            int b = 2 * j;
            int c = 2 * k;
            G[a].push_back(b ^ 1);
            G[a].push_back(c ^ 1);
            G[b].push_back(a ^ 1);
            G[b].push_back(c);
            G[c].push_back(a ^ 1);
            G[c].push_back(b);
            G[a ^ 1].push_back(b);
            G[a ^ 1].push_back(c);
            G[b ^ 1].push_back(a);
            G[b ^ 1].push_back(c ^ 1);
            G[c ^ 1].push_back(a);
            G[c ^ 1].push_back(b ^ 1);
        }
    
        bool Solve()
        {
            for (int i = 0; i < 2 * n; 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;
        }
    };
    
    TwoSAT sat;
    int main()
    {
        int n, m;
    
        while (scanf("%d %d", &n, &m) != EOF)
        {
            int a, b, c;
            sat.Init(3 * n);
            for (int i = 0; i < n; ++i)
            {
                scanf("%d %d %d", &a, &b, &c);
                sat.AddClauseTeam(a, b, c);
            }
            for (int i = 0; i < m; ++i)
            {
                scanf("%d %d", &a, &b);
                sat.AddClause(a, b);
            }
    
            bool ok = sat.Solve();
            if (ok)
                printf("yes
    ");
            else
                printf("no
    ");
        }
        return 0;
    }
  • 相关阅读:
    静态页面复习--网格嵌套练习
    静态页面复习--用semantic UI写苹果官网
    静态页面复习--用网格写一个landing page
    静态页面复习--用semantic UI画美国队长盾牌
    静态页面复习--semantic UI搭建简单博客页面
    SQL脚本--总耗CPU最多的前个SQL --平均耗CPU最多的前个SQL
    C#中基于GDI+(Graphics)图像处理系列
    MVC Action 返回类型
    Axure RP 7 8
    MVC object htmlAttributes,IDictionary<string, object> htmlAttributes 写法
  • 原文地址:https://www.cnblogs.com/tallisHe/p/4681259.html
Copyright © 2011-2022 走看看