|
| 1 | +#ifndef AFGR_2SAT |
| 2 | +#define AFGR_2SAT |
| 3 | + |
| 4 | +#include <vector> |
| 5 | + |
| 6 | +struct TwoSAT { |
| 7 | + std::vector<std::vector<int>> G; |
| 8 | + std::vector<int> dfn, low, stk, bel, in; |
| 9 | + TwoSAT(void) = default; |
| 10 | + TwoSAT(int n) : G(2 * n) {} |
| 11 | + void tarjan(int u, int &cnt, int &cc) { |
| 12 | + dfn[u] = low[u] = ++cnt; |
| 13 | + in[u] = 1, stk.push_back(u); |
| 14 | + for (auto &v : G[u]) { |
| 15 | + if (dfn[v] == 0) { |
| 16 | + tarjan(v, cnt, cc); |
| 17 | + low[u] = std::min(low[u], low[v]); |
| 18 | + } else if (in[v]) { |
| 19 | + low[u] = std::min(low[u], dfn[v]); |
| 20 | + } |
| 21 | + } |
| 22 | + int v; |
| 23 | + if (dfn[u] == low[u]) { |
| 24 | + cc++; |
| 25 | + do { |
| 26 | + v = stk.back(), in[v] = 0; |
| 27 | + stk.pop_back(), bel[v] = cc; |
| 28 | + } while (v != u); |
| 29 | + } |
| 30 | + } |
| 31 | + // Add constraint: x = a or y = b. |
| 32 | + inline void add(int x, bool a, int y, bool b) { |
| 33 | + size_t should = 2 * (std::max(x, y) + 1); |
| 34 | + if (G.size() < should) G.resize(should); |
| 35 | + G[x << 1 | !a].push_back(y << 1 | b); |
| 36 | + G[y << 1 | !b].push_back(x << 1 | a); |
| 37 | + } |
| 38 | + inline void init(void) { // find scc. |
| 39 | + int n = G.size(), cnt = 0, cc = 0; |
| 40 | + in = dfn = low = bel = std::vector<int>(n, 0); |
| 41 | + for (int i = 0; i < n; i++) { |
| 42 | + if (!dfn[i]) tarjan(i, cnt, cc); |
| 43 | + } |
| 44 | + } |
| 45 | + inline bool has_solution(void) { |
| 46 | + int var = G.size() / 2; |
| 47 | + for (int i = 0; i < var; i++) { |
| 48 | + if (bel[i << 1] == bel[i << 1 | 1]) { |
| 49 | + return false; |
| 50 | + } |
| 51 | + } |
| 52 | + return true; |
| 53 | + } |
| 54 | + std::vector<int> solve(int n) { |
| 55 | + int var = G.size() / 2; |
| 56 | + std::vector<int> sol(n); |
| 57 | + for (int i = 0; i < var; i++) { |
| 58 | + sol[i] = bel[i << 1] > bel[i << 1 | 1]; |
| 59 | + } |
| 60 | + return sol; |
| 61 | + } |
| 62 | +}; |
| 63 | + |
| 64 | +#endif |
0 commit comments