Implement `is_bipartite_graph`
diff --git a/src/algo/mod.rs b/src/algo/mod.rs
index aa54405..ab558a6 100644
--- a/src/algo/mod.rs
+++ b/src/algo/mod.rs
@@ -791,6 +791,60 @@
     Ok((distance, predecessor))
 }
 
+/// Return `true` if the graph is bipartite. A graph is bipartite if it's nodes can be divided into
+/// two disjoint and indepedent sets U and V such that every edge connects U to one in V. This
+/// algorithm implements 2-coloring algorithm based on the BFS algorithm.
+///
+/// Always treats the input graph as if undirected.
+pub fn is_bipartite_undirected<G, N, VM>(g: G, start: N) -> bool
+    where G: GraphRef + Visitable<NodeId=N, Map=VM> + IntoNeighbors<NodeId=N>,
+          N: Copy + PartialEq + std::fmt::Debug,
+          VM: VisitMap<N>
+{
+    let mut red = g.visit_map();
+    red.visit(start);
+    let mut blue = g.visit_map();
+
+    let mut stack = ::std::collections::VecDeque::new();
+    stack.push_front(start);
+
+    while let Some(node) = stack.pop_front() {
+        let is_red = red.is_visited(&node);
+        let is_blue = blue.is_visited(&node);
+
+        assert!(is_red ^ is_blue);
+
+        for neighbour in g.neighbors(node) {
+            let is_neigbour_red = red.is_visited(&neighbour);
+            let is_neigbour_blue = blue.is_visited(&neighbour);
+
+            if (is_red && is_neigbour_red) || (is_blue && is_neigbour_blue) {
+                return false;
+            }
+
+            /*
+            if is_red && is_neigbour_blue || is_blue && is_neigbour_red {
+                //good
+            }
+            */
+
+            if !is_neigbour_red && !is_neigbour_blue {
+                //hasn't been visited yet
+
+                match (is_red, is_blue) {
+                    (true, false) => { blue.visit(neighbour); },
+                    (false, true) => { red.visit(neighbour); },
+                    (_, _) => { panic!("Invariant doesn't hold"); }
+                }
+
+                stack.push_back(neighbour);
+            }
+        }
+    }
+
+    true
+}
+
 use std::fmt::Debug;
 use std::ops::Add;
 
diff --git a/tests/graph.rs b/tests/graph.rs
index a8e4097..a33977a 100644
--- a/tests/graph.rs
+++ b/tests/graph.rs
@@ -9,7 +9,7 @@
 use petgraph as pg;
 
 use petgraph::algo::{
-    dominators, has_path_connecting, is_cyclic_undirected, is_isomorphic_matching,
+    dominators, has_path_connecting, is_cyclic_undirected, is_isomorphic_matching, is_bipartite_undirected,
     min_spanning_tree,
 };
 
@@ -280,6 +280,77 @@
 }
 
 #[test]
+fn bipartite() {
+    {
+        let mut gr = Graph::new_undirected();
+        let a = gr.add_node("A");
+        let b = gr.add_node("B");
+        let c = gr.add_node("C");
+
+        let d = gr.add_node("D");
+        let e = gr.add_node("E");
+        let f = gr.add_node("F");
+
+        gr.add_edge(a, d, 7.);
+        gr.add_edge(b, d, 6.);
+
+        assert!(is_bipartite_undirected(&gr, a));
+
+        let e_index = gr.add_edge(a, b, 6.);
+
+        assert!(!is_bipartite_undirected(&gr, a));
+
+        gr.remove_edge(e_index);
+
+        assert!(is_bipartite_undirected(&gr, a));
+
+        gr.add_edge(b, e, 7.);
+        gr.add_edge(b, f, 6.);
+        gr.add_edge(c, e, 6.);
+
+        assert!(is_bipartite_undirected(&gr, a));
+    }
+    {
+        let mut gr = Graph::new_undirected();
+        let a = gr.add_node("A");
+        let b = gr.add_node("B");
+        let c = gr.add_node("C");
+        let d = gr.add_node("D");
+        let e = gr.add_node("E");
+
+        let f = gr.add_node("F");
+        let g = gr.add_node("G");
+        let h = gr.add_node("H");
+
+        gr.add_edge(a, f, 7.);
+        gr.add_edge(a, g, 7.);
+        gr.add_edge(a, h, 7.);
+
+        gr.add_edge(b, f, 6.);
+        gr.add_edge(b, g, 6.);
+        gr.add_edge(b, h, 6.);
+
+        gr.add_edge(c, f, 6.);
+        gr.add_edge(c, g, 6.);
+        gr.add_edge(c, h, 6.);
+
+        gr.add_edge(d, f, 6.);
+        gr.add_edge(d, g, 6.);
+        gr.add_edge(d, h, 6.);
+
+        gr.add_edge(e, f, 6.);
+        gr.add_edge(e, g, 6.);
+        gr.add_edge(e, h, 6.);
+
+        assert!(is_bipartite_undirected(&gr, a));
+
+        gr.add_edge(a, b, 6.);
+
+        assert!(!is_bipartite_undirected(&gr, a));
+    }
+}
+
+#[test]
 fn multi() {
     let mut gr = Graph::new();
     let a = gr.add_node("a");