1
+ //! A 2-SAT Solver.
1
2
use crate :: internal_scc;
2
3
4
+ /// A 2-SAT Solver.
5
+ ///
6
+ /// For variables $x_0, x_1, \ldots, x_{N - 1}$ and clauses with from
7
+ ///
8
+ /// \\[
9
+ /// (x_i = f) \lor (x_j = g)
10
+ /// \\]
11
+ ///
12
+ /// it decides whether there is a truth assignment that satisfies all clauses.
13
+ ///
14
+ /// # Example
15
+ ///
16
+ /// ```
17
+ /// #![allow(clippy::many_single_char_names)]
18
+ ///
19
+ /// use ac_library_rs::TwoSat;
20
+ /// use proconio::{input, marker::Bytes, source::once::OnceSource};
21
+ ///
22
+ /// input! {
23
+ /// from OnceSource::from(
24
+ /// "3\n\
25
+ /// 3\n\
26
+ /// a b\n\
27
+ /// !b c\n\
28
+ /// !a !a\n",
29
+ /// ),
30
+ /// n: usize,
31
+ /// pqs: [(Bytes, Bytes)],
32
+ /// }
33
+ ///
34
+ /// let mut twosat = TwoSat::new(n);
35
+ ///
36
+ /// for (p, q) in pqs {
37
+ /// fn parse(s: &[u8]) -> (usize, bool) {
38
+ /// match *s {
39
+ /// [c] => ((c - b'a').into(), true),
40
+ /// [b'!', c] => ((c - b'a').into(), false),
41
+ /// _ => unreachable!(),
42
+ /// }
43
+ /// }
44
+ /// let ((i, f), (j, g)) = (parse(&p), parse(&q));
45
+ /// twosat.add_clause(i, f, j, g);
46
+ /// }
47
+ ///
48
+ /// assert!(twosat.satisfiable());
49
+ /// assert_eq!(twosat.answer(), [false, true, true]);
50
+ /// ```
3
51
pub struct TwoSat {
4
52
n : usize ,
5
53
scc : internal_scc:: SccGraph ,
6
54
answer : Vec < bool > ,
7
55
}
8
56
impl TwoSat {
57
+ /// Creates a new `TwoSat` of `n` variables and 0 clauses.
58
+ ///
59
+ /// # Constraints
60
+ ///
61
+ /// - $0 \leq n \leq 10^8$
62
+ ///
63
+ /// # Complexity
64
+ ///
65
+ /// - $O(n)$
9
66
pub fn new ( n : usize ) -> Self {
10
67
TwoSat {
11
68
n,
12
69
answer : vec ! [ false ; n] ,
13
70
scc : internal_scc:: SccGraph :: new ( 2 * n) ,
14
71
}
15
72
}
73
+ /// Adds a clause $(x_i = f) \lor (x_j = g)$.
74
+ ///
75
+ /// # Constraints
76
+ ///
77
+ /// - $0 \leq i < n$
78
+ /// - $0 \leq j < n$
79
+ ///
80
+ /// # Panics
81
+ ///
82
+ /// Panics if the above constraints are not satisfied.
83
+ ///
84
+ /// # Complexity
85
+ ///
86
+ /// - $O(1)$ amortized
16
87
pub fn add_clause ( & mut self , i : usize , f : bool , j : usize , g : bool ) {
17
88
assert ! ( i < self . n && j < self . n) ;
18
89
self . scc . add_edge ( 2 * i + !f as usize , 2 * j + g as usize ) ;
19
90
self . scc . add_edge ( 2 * j + !g as usize , 2 * i + f as usize ) ;
20
91
}
92
+ /// Returns whether there is a truth assignment that satisfies all clauses.
93
+ ///
94
+ /// # Complexity
95
+ ///
96
+ /// - $O(n + m)$ where $m$ is the number of added clauses
21
97
pub fn satisfiable ( & mut self ) -> bool {
22
98
let id = self . scc . scc_ids ( ) . 1 ;
23
99
for i in 0 ..self . n {
@@ -28,6 +104,17 @@ impl TwoSat {
28
104
}
29
105
true
30
106
}
107
+ /// Returns a truth assignment that satisfies all clauses **of the last call of [`satisfiable`]**.
108
+ ///
109
+ /// # Constraints
110
+ ///
111
+ /// - [`satisfiable`] is called after adding all clauses and it has returned `true`.
112
+ ///
113
+ /// # Complexity
114
+ ///
115
+ /// - $O(n)$
116
+ ///
117
+ /// [`satisfiable`]: #method.satisfiable
31
118
pub fn answer ( & self ) -> & [ bool ] {
32
119
& self . answer
33
120
}
0 commit comments