-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy path2sat.cpp
More file actions
84 lines (71 loc) · 1.53 KB
/
2sat.cpp
File metadata and controls
84 lines (71 loc) · 1.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
* 2SAT Solver
*
* Usage:
*
* Add edges with AddEdge(u, v)
* where u < 0 if not |u| and u > 0 if |u|
* (edges are of type u -> v), and call Solve().
*
* The answer is in TwoSAT::Sol. If there is
* no solution, no_sol will be set to true.
*
* Also, keep in mind the 1-indexing of literals!
**/
class TwoSAT {
vector<vector<int>> G, G_T;
vector<int> Viz;
vector<bool> Sol, True;
vector<int> Stack;
bool no_sol;
int n;
void dfs_forward(int node) {
Viz[node] = true;
for(auto vec : G[node]) {
if(!Viz[vec])
dfs_forward(vec);
}
Stack.push_back(node);
}
void dfs_backward(int node) {
// Set node's truth value to false
if(True[node])
no_sol = true;
Viz[node] = true;
True[node ^ 1] = true;
Sol[node / 2] = ((node & 1) ^ 1);
// Whatever implies false is false
for(auto vec : G_T[node]) {
if(!Viz[vec])
dfs_backward(vec);
}
}
int get_node(int x) {
if (x > 0) return 2 * (x - 1) + 1;
return 2 * (-x - 1);
}
public:
TwoSAT(int n) : G(2 * n), G_T(2 * n), Viz(2 * n),
Sol(n, 0), True(2 * n, 0), n(n) {
Stack.reserve(2 * n);
}
void add_edge(int a, int b) {
a = get_node(a); b = get_node(b);
G[a].push_back(b);
G_T[b].push_back(a);
}
pair<bool, vector<bool>> solve() {
fill(Viz.begin(), Viz.end(), 0);
for(int i = 0; i < 2 * n; ++i) {
if(!Viz[i])
dfs_forward(i);
}
no_sol = false;
fill(Viz.begin(), Viz.end(), 0);
for(int i = 2 * n - 1; i >= 0; --i) {
if(!Viz[Stack[i]] && !Viz[Stack[i] ^ 1])
dfs_backward(Stack[i]);
}
return {!no_sol, Sol};
}
};