1use crate::graph::{scc::*, *};
3
4pub struct TwoSat {
6 size: usize,
7 g: Graph<Directed, Edge<(), ()>>,
8}
9
10impl TwoSat {
11 pub fn new(size: usize) -> Self {
13 Self {
14 size,
15 g: Graph::new(2 * size),
16 }
17 }
18
19 fn check(&self, x: isize) -> usize {
20 assert!(x != 0);
21 assert!(x.unsigned_abs() <= self.size);
22
23 if x > 0 {
24 x as usize - 1
25 } else {
26 x.unsigned_abs() + self.size - 1
27 }
28 }
29
30 pub fn add_if(&mut self, a: isize, b: isize) {
32 self.g.add(Edge::new(self.check(a), self.check(b), (), ()));
33 }
34
35 pub fn add_or(&mut self, a: isize, b: isize) {
37 self.add_if(-a, b);
38 self.add_if(-b, a);
39 }
40
41 pub fn not_coexist(&mut self, a: isize, b: isize) {
43 self.add_or(-a, -b);
44 }
45
46 pub fn solve(&self) -> Option<Vec<bool>> {
48 let s = SCC::new(&self.g);
49 let s = s.index();
50
51 let (a, b) = s.split_at(self.size);
52 if a.iter().zip(b).any(|(a, b)| a == b) {
53 return None;
54 }
55
56 Some(a.iter().zip(b).map(|(a, b)| a > b).collect())
57 }
58}