http://codeforces.com/contest/776/problem/D 2-sat

/*2-sat启蒙题目*/
/*其实2-sat我个人理解就是根据题目写出最终答案必然出现的情况的关系(可能多个) 然后判断能不能构成连通图*/

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <stack>
#include <queue>
using namespace std;

const int maxn = 3e5;

int n, m, tot;
int door[maxn];
int mark[maxn];
vector<int>G[maxn];
vector<int>v[maxn];
int c = 0;
int s[maxn];

void addedge(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);
}

bool dfs(int x) {
    if (mark[x ^ 1]) return false;
    if (mark[x]) return true;
    mark[x] = true;
    s[c++] = x;
    int len = G[x].size();
    for (int i = 0; i < len; ++i) {
        if (!dfs(G[x][i]))
            return false;
    }
    return true;
}

bool solve() {
    for (int i = 0; i < m * 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;
}

void test() {
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 0; i < n; ++i) cin >> door[i];
    for (int i = 0; i < m; ++i) {
        int x; cin >> x;
        for (int j = 0; j < x; ++j) {
            int y; cin >> y;
            v[y - 1].push_back(i);
        }
    }
    for (int i = 0; i < m * 2; ++i)
        G[i].clear();
    memset(mark, 0, sizeof mark);
    for (int i = 0; i < n; ++i) {
        if (door[i]) {
            addedge(v[i][0], 0, v[i][1], 1);
            addedge(v[i][0], 1, v[i][1], 0);
        }
        else {
            addedge(v[i][0], 0, v[i][1], 0);
            addedge(v[i][0], 1, v[i][1], 1);
        }
    }
    cout << (solve() ? "YES" : "NO") << endl;
}


int main() {
    test();
    return 0;
}
原文地址:https://www.cnblogs.com/boson-is-god/p/6477074.html