Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bd0074c

Browse files
committed
Bipartite Graph Check added
1 parent ac21c2c commit bd0074c

File tree

2 files changed

+204
-1
lines changed

2 files changed

+204
-1
lines changed
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
**
2+
* This file shows you how to determine if a graph is bipartite or not. This can be achieved in
3+
* linear time by coloring the visited nodes.
4+
*
5+
* <p>Time Complexity: O(V + E)
6+
*
7+
* @author William Fiset, william.alexandre.fiset@gmail.com
8+
*/
9+
10+
import com.williamfiset.algorithms.utils.graphutils.Utils;
11+
import java.util.List;
12+
13+
public class BipartiteGraphCheckAdjacencyList {
14+
15+
private int n;
16+
private int[] colors;
17+
private boolean solved;
18+
private boolean isBipartite;
19+
private List<List<Integer>> graph;
20+
21+
public static final int RED = 0b10, BLACK = (RED ^ 1);
22+
23+
public BipartiteGraphCheckAdjacencyList(List<List<Integer>> graph) {
24+
if (graph == null) throw new IllegalArgumentException("Graph cannot be null.");
25+
n = graph.size();
26+
this.graph = graph;
27+
}
28+
29+
// Checks whether the input graph is bipartite.
30+
public boolean isBipartite() {
31+
if (!solved) solve();
32+
return isBipartite;
33+
}
34+
35+
// If the input graph is bipartite it has a two coloring which can be obtained
36+
// through this method. Each index in the returned array is either RED or BLACK
37+
// indicating which color node i was colored.
38+
public int[] getTwoColoring() {
39+
return isBipartite() ? colors : null;
40+
}
41+
42+
private void solve() {
43+
if (n <= 1) return;
44+
45+
colors = new int[n];
46+
int nodesVisited = colorGraph(0, RED);
47+
48+
// The graph is not bipartite. Either not all the nodes were visited or the
49+
// colorGraph method returned -1 meaning the graph is not 2-colorable.
50+
isBipartite = (nodesVisited == n);
51+
solved = true;
52+
}
53+
54+
// Do a depth first search coloring the nodes of the graph as we go.
55+
// This method returns the count of the number of nodes visited while
56+
// coloring the graph or -1 if this graph is not bipartite.
57+
private int colorGraph(int i, int color) {
58+
colors[i] = color;
59+
60+
// Toggles the color between RED and BLACK by exploiting the binary representation
61+
// of the constants and flipping the least significant bit on and off.
62+
int nextColor = (color ^ 1);
63+
64+
int visitCount = 1;
65+
List<Integer> edges = graph.get(i);
66+
67+
for (int to : edges) {
68+
// Contradiction found. In a bipartite graph no two
69+
// nodes of the same color can be next to each other!
70+
if (colors[to] == color) return -1;
71+
if (colors[to] == nextColor) continue;
72+
73+
// If a contradiction is found propagate return -1
74+
// otherwise keep track of the number of visited nodes.
75+
int count = colorGraph(to, nextColor);
76+
if (count == -1) return -1;
77+
visitCount += count;
78+
}
79+
80+
return visitCount;
81+
}
82+
83+
/* Example usage */
84+
85+
public static void main(String[] args) {
86+
87+
// Singleton (not bipartite)
88+
int n = 1;
89+
List<List<Integer>> graph = Utils.createEmptyAdjacencyList(n);
90+
Utils.addUndirectedEdge(graph, 0, 0);
91+
displayGraph(graph);
92+
93+
// Prints:
94+
// Graph has 1 node(s) and the following edges:
95+
// 0 -> 0
96+
// 0 -> 0
97+
// This graph is bipartite: false
98+
99+
// Two nodes one edge between them (bipartite)
100+
n = 2;
101+
graph = Utils.createEmptyAdjacencyList(n);
102+
Utils.addUndirectedEdge(graph, 0, 1);
103+
displayGraph(graph);
104+
105+
// Prints:
106+
// Graph has 2 node(s) and the following edges:
107+
// 0 -> 1
108+
// 1 -> 0
109+
// This graph is bipartite: true
110+
111+
// Triangle graph (not bipartite)
112+
n = 3;
113+
graph = Utils.createEmptyAdjacencyList(n);
114+
Utils.addUndirectedEdge(graph, 0, 1);
115+
Utils.addUndirectedEdge(graph, 1, 2);
116+
Utils.addUndirectedEdge(graph, 2, 0);
117+
displayGraph(graph);
118+
119+
// Prints:
120+
// Graph has 3 node(s) and the following edges:
121+
// 0 -> 1
122+
// 0 -> 2
123+
// 1 -> 0
124+
// 1 -> 2
125+
// 2 -> 1
126+
// 2 -> 0
127+
// This graph is bipartite: false
128+
129+
// Disjoint graph is bipartite connected components (altogether not bipartite)
130+
n = 4;
131+
graph = Utils.createEmptyAdjacencyList(n);
132+
Utils.addUndirectedEdge(graph, 0, 1);
133+
Utils.addUndirectedEdge(graph, 2, 3);
134+
displayGraph(graph);
135+
136+
// Prints:
137+
// Graph has 4 node(s) and the following edges:
138+
// 0 -> 1
139+
// 1 -> 0
140+
// 2 -> 3
141+
// 3 -> 2
142+
// This graph is bipartite: false
143+
144+
// Square graph (bipartite)
145+
n = 4;
146+
graph = Utils.createEmptyAdjacencyList(n);
147+
Utils.addUndirectedEdge(graph, 0, 1);
148+
Utils.addUndirectedEdge(graph, 1, 2);
149+
Utils.addUndirectedEdge(graph, 2, 3);
150+
Utils.addUndirectedEdge(graph, 3, 0);
151+
displayGraph(graph);
152+
153+
// Prints:
154+
// Graph has 4 node(s) and the following edges:
155+
// 0 -> 1
156+
// 0 -> 3
157+
// 1 -> 0
158+
// 1 -> 2
159+
// 2 -> 1
160+
// 2 -> 3
161+
// 3 -> 2
162+
// 3 -> 0
163+
// This graph is bipartite: true
164+
165+
// Square graph with additional edge (not bipartite)
166+
n = 4;
167+
graph = Utils.createEmptyAdjacencyList(n);
168+
Utils.addUndirectedEdge(graph, 0, 1);
169+
Utils.addUndirectedEdge(graph, 1, 2);
170+
Utils.addUndirectedEdge(graph, 2, 3);
171+
Utils.addUndirectedEdge(graph, 3, 0);
172+
Utils.addUndirectedEdge(graph, 0, 2);
173+
displayGraph(graph);
174+
175+
// Prints:
176+
// Graph has 4 node(s) and the following edges:
177+
// 0 -> 1
178+
// 0 -> 3
179+
// 0 -> 2
180+
// 1 -> 0
181+
// 1 -> 2
182+
// 2 -> 1
183+
// 2 -> 3
184+
// 2 -> 0
185+
// 3 -> 2
186+
// 3 -> 0
187+
// This graph is bipartite: false
188+
189+
}
190+
191+
private static void displayGraph(List<List<Integer>> graph) {
192+
final int n = graph.size();
193+
194+
System.out.println("Graph has " + n + " node(s) and the following edges:");
195+
for (int f = 0; f < n; f++) for (int t : graph.get(f)) System.out.println(f + " -> " + t);
196+
197+
BipartiteGraphCheckAdjacencyList solver;
198+
solver = new BipartiteGraphCheckAdjacencyList(graph);
199+
200+
System.out.println("This graph is bipartite: " + (solver.isBipartite()));
201+
System.out.println();
202+
}
203+
}

‎README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ In mathematics and computer science, an algorithm is a finite sequence of well-d
156156
- [Min Cost Max Flow](https://github.com/lemidia/Algorithm-and-Data-Structure/blob/master/AlgorithmCode/MinCostMaxFlow.java) - 최소비용 최대유량 알고리즘, 최소비용에는 SPFA Algorithm, 최대비용에는 Edmonds Karp Algorithm 적용
157157

158158
### Bipartite Matching - 이분매칭
159-
- Bipartite Matching - DFS Manner
159+
- [Bipartite Matching](https://github.com/lemidia/Algorithm-and-Data-Structure/blob/master/BipartiteGraphCheckAdjacencyList.java) - DFS Manner
160160

161161
### Strongly Connected Component - 강한 연결 요소
162162
- [Tarjan's Algorithm](https://github.com/lemidia/Algorithm-and-Data-Structure/blob/master/AlgorithmCode/TarjanScc.java) - O(V+E)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /