use std::collections::VecDeque;

struct Solution {}
impl Solution {
    fn color(graph: &Vec<Vec<i32>>, start: usize, colors: &mut Vec<i32>) -> bool {
        let mut q: VecDeque<usize> = VecDeque::new();
        q.push_back(start);

        while let Some(u) = q.pop_front() {
            let u_color = colors[u];

            let next_color = (colors[u] + 1) % 2;
            for v in &graph[u] {
                let v = *v as usize;
                match colors[v] {
                    -1 => {
                        colors[v] = next_color;
                        q.push_back(v);
                    }
                    _ => {
                        if colors[v] != next_color {
                            return false;
                        }
                    }
                }
            }
        }

        true
    }

    pub fn is_bipartite(graph: Vec<Vec<i32>>) -> bool {
        let mut colors = vec![-1; graph.len()];

        for u in 0..graph.len() {
            if colors[u] != -1 {
                continue;
            }

            colors[u] = 0;
            if !Solution::color(&graph, u, &mut colors) {
                return false;
            }
        }

        true
    }
}

fn main() {}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn example_1() {
        assert!(!Solution::is_bipartite(vec![
            vec![1, 2, 3],
            vec![0, 2],
            vec![0, 1, 3],
            vec![0, 2]
        ]));
    }

    #[test]
    fn example_2() {
        assert!(Solution::is_bipartite(vec![
            vec![1, 3],
            vec![0, 2],
            vec![1, 3],
            vec![0, 2]
        ]));
    }
}