ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2-SAT - 2019.10.7 聚会

2019-11-07 22:07:59  阅读:268  来源: 互联网

标签:2019.10 color sp ++ int dfn low 聚会 SAT


题面

【问题描述】

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

【输入格式】

包含多组数据,对于每一组数据:

第一行一个正整数 \(n\),表示有 \(n\) 对夫妻被邀请 (\(n\le 1000\))

第二行一个正整数 \(m\),表示有 \(m\) 对矛盾关系 ( \(m < (n - 1)^2\))

在接下来的 \(m\) 行中,每行会有 \(4\) 个数字,分别是 \(A_1,A_2,C_1,C_2\)

\(A_1,A_2\) 分别表示是夫妻的编号, \(C_1,C_2\) 表示是妻子还是丈夫 ,\(0\) 表示妻子 ,\(1\) 是丈夫

夫妻编号从 \(0\) 到 \(n -1\)

【输出格式】

如果存在一种可以 \(n\) 个人同时列席的情况,则输出 YES,否则输出 NO

【输入样例】

2
1
0 1 1 1

【输出样例】

YES

【数据范围】

每个数据不超过10组。

实际上,此题的描述是不完全的,但是在(多次)估摸提议后仍然通过了此题。这题是一道简单的 2-SAT 问题。设 \(P_i\) 表示第 \(i\) 对夫妻中丈夫去,否则妻子去,可以建图。

程序

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
 
#define MAXN 1020
int n, m;
vector<int> g[2 * MAXN];
int dfn[2 * MAXN], color[2 * MAXN], low[2 * MAXN], s[2 * MAXN], sp, cnt, col;
 
void tarjan(int u) {
    dfn[u] = low[u] = ++cnt;
//  s.push(u);
    s[++sp] = u;
    for (vector<int>::iterator it = g[u].begin(); it != g[u].end(); it++) {
        if (!dfn[*it]) {
            tarjan(*it);
            low[u] = min(low[u], low[*it]);
        } else if (!color[*it]) {
            low[u] = min(low[u], low[*it]);
        }
    }
     
    if (low[u] == dfn[u]) {
        color[u] = ++col;
        while (s[sp] != u) {
            color[s[sp]] = color[u];
            sp--;
        }
        sp--;
    }
}
 
void solve() {
    memset(dfn, 0, sizeof(dfn));
    memset(color, 0, sizeof(color));
    memset(low, 0, sizeof(low));
    memset(s, 0, sizeof(s));
    cnt = col = sp = 0;
    cin >> m;
    for (int i = 0; i < 2 * n; i++)
        g[i].clear();
    for (int i = 0; i < m; i++) {
        int a1, a2, c1, c2;
        cin >> a1 >> a2 >> c1 >> c2;
//        cout << " " << a1 + c1 * n << " " << a2 + c2 * n << endl;
        g[a1 + c1 * n].push_back(a2 + (1 - c2) * n);
        g[a2 + c2 * n].push_back(a1 + (1 - c1) * n);
    }
    for (int i = 0; i < 2 * n; i++)
        if (!dfn[i]) tarjan(i);
    for (int i = 0; i < n; i++)
        if (color[i] == color[i + n]) {
            cout << "NO" << endl;
            return;
        }
    cout << "YES" << endl;    
}
 
int main() {
    while (cin >> n) {
        solve();
    }
    return 0;
}

标签:2019.10,color,sp,++,int,dfn,low,聚会,SAT
来源: https://www.cnblogs.com/lrw04/p/11815947.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有