zoukankan      html  css  js  c++  java
  • hdoj 3062 Party(2-SAT)

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

    思路分析:将问题转换为2-SAT问题,需要注意的是将命题转换为有向图的方法;命题中A1, A2, C1, C2表示C1与C2不能同时出现,所以A1中C1出现等价于A2中C2 ^ 1出现,同理A2中C2出现等价于A1中C1^1出现,则形成了两条有向边;

    代码如下:

    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    const int MAX_N = 1000 + 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 x_val, int y, int y_val)
        {
            x = 2 * x + x_val;
            y = 2 * y + y_val;
            G[x].push_back(y ^ 1);
            G[y].push_back(x ^ 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", &n) != EOF)
        {
            scanf("%d", &m);
            sat.Init(n);
            for (int i = 0; i < m; ++i)
            {
                int x, x_val, y, y_val;
                scanf("%d %d %d %d", &x, &y, &x_val, &y_val);
                sat.AddClause(x, x_val, y, y_val);
            }
            bool ans = sat.Solve();
            if (ans)
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }
  • 相关阅读:
    【题解】【神奇校内POIN模拟赛】小凯的疑惑
    【题解】【CF670C】cinema
    11 Remove Duplicates from Sorted Array II
    10 3SumClosest
    7 Container With Most Water
    8 String to Integer (atoi)
    9 3Sum
    6 Palindrome Number
    5 Zigzag Conversion
    4 Longest Palindromic Substring
  • 原文地址:https://www.cnblogs.com/tallisHe/p/4680918.html
Copyright © 2011-2022 走看看