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; }