competitive/algorithm/
chromatic_number.rs1use super::{MInt, MIntBase, One, Zero, binary_search};
2
3#[derive(Debug, Clone)]
4pub struct IndependentSubSet<M>
5where
6 M: MIntBase,
7{
8 pub n: usize,
9 pub ind: Vec<MInt<M>>,
10}
11
12impl<M> IndependentSubSet<M>
13where
14 M: MIntBase,
15{
16 pub fn from_edges(n: usize, edges: &[(usize, usize)]) -> Self {
17 let mut g = vec![0; n];
18 for &(u, v) in edges {
19 g[u] |= 1 << v;
20 g[v] |= 1 << u;
21 }
22 Self::from_adj_graph(&g)
23 }
24
25 pub fn from_adj_graph(g: &[usize]) -> Self {
26 let n = g.len();
27 let mut ind = Vec::with_capacity(1 << n);
28 ind.push(MInt::one());
29 for s in 1usize..1 << n {
30 let v = s.trailing_zeros() as usize;
31 ind.push(ind[s - (1 << v)] + ind[s & !(g[v] | (1 << v))]);
32 }
33 Self { n, ind }
34 }
35
36 pub fn k_colorable(&self, k: usize) -> bool {
37 !self
38 .ind
39 .iter()
40 .map(|d| d.pow(k))
41 .enumerate()
42 .map(|(s, d)| if s.count_ones() % 2 == 0 { d } else { -d })
43 .sum::<MInt<M>>()
44 .is_zero()
45 }
46
47 pub fn chromatic_number(&self) -> usize {
49 binary_search(|&k| self.k_colorable(k), self.n, 0)
50 }
51}