Skip to content

Commit 456ea79

Browse files
committed
added two sat and unittest
1 parent 85b7747 commit 456ea79

2 files changed

Lines changed: 104 additions & 0 deletions

File tree

src/alfred/graph/twosat.hpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// competitive-verifier: PROBLEM https://judge.yosupo.jp/problem/two_sat
2+
3+
#include "../../src/alfred/config/io-sync-off.hpp"
4+
#include "../../src/alfred/graph/twosat.hpp"
5+
#include <iostream>
6+
7+
int main(int argc, char const *argv[]) {
8+
std::string s;
9+
int n, m, x, y, v;
10+
optimizeIO(), std::cin >> s >> s >> n >> m;
11+
12+
TwoSAT TS(n);
13+
14+
while (m--) {
15+
std::cin >> x >> y >> v;
16+
bool v1 = true, v2 = true;
17+
if (x < 0) v1 = false, x = -x;
18+
if (y < 0) v2 = false, y = -y;
19+
TS.add(x - 1, v1, y - 1, v2);
20+
}
21+
22+
TS.init();
23+
24+
if (TS.has_solution()) {
25+
std::cout << "s SATISFIABLE\nv ";
26+
std::vector<int> res = TS.solve(n);
27+
for (int i = 0; i < n; i++) {
28+
if (res[i] == 0) {
29+
std::cout << -(i + 1) << ' ';
30+
} else {
31+
std::cout << i + 1 << ' ';
32+
}
33+
}
34+
std::cout << "0\n";
35+
} else {
36+
std::cout << "s UNSATISFIABLE\n";
37+
}
38+
39+
return 0;
40+
}

0 commit comments

Comments
 (0)