diff --git a/DIRECTORY.md b/DIRECTORY.md index 7e9f5357a825..d3136f95c062 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -676,6 +676,7 @@ * dynamicarray * [DynamicArrayTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/dynamicarray/DynamicArrayTest.java) * graphs + * [BipartiteGraphDFSTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFSTest.java) * [BoruvkaAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithmTest.java) * [DijkstraAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java) * [EdmondsBlossomAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/EdmondsBlossomAlgorithmTest.java) diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFS.java b/src/main/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFS.java index e8d2b8fd0a04..15ae5225533c 100644 --- a/src/main/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFS.java +++ b/src/main/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFS.java @@ -1,23 +1,49 @@ package com.thealgorithms.datastructures.graphs; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; /** - * Given an adjacency list of a graph adj of V no. of vertices having 0 based - * index. Check whether the graph is bipartite or not. + * This class provides a method to check if a given undirected graph is bipartite using Depth-First Search (DFS). + * A bipartite graph is a graph whose vertices can be divided into two disjoint sets such that no two vertices + * within the same set are adjacent. In other words, all edges must go between the two sets. * - * Input : {{0, 1, 0, 1}, {1, 0, 1, 0}, {0, 1, 0, 1}, {1, 0, 1, 0}} + * The implementation leverages DFS to attempt to color the graph using two colors. If we can color the graph such + * that no two adjacent vertices have the same color, the graph is bipartite. * - * Output : YES + * Example: + * Input (Adjacency Matrix): + * {{0, 1, 0, 1}, + * {1, 0, 1, 0}, + * {0, 1, 0, 1}, + * {1, 0, 1, 0}} + * + * Output: YES (This graph is bipartite) + * + * Input (Adjacency Matrix): + * {{0, 1, 1, 0}, + * {1, 0, 1, 0}, + * {1, 1, 0, 1}, + * {0, 0, 1, 0}} + * + * Output: NO (This graph is not bipartite) */ public final class BipartiteGraphDFS { private BipartiteGraphDFS() { } + /** + * Helper method to perform DFS and check if the graph is bipartite. + * + * During DFS traversal, this method attempts to color each vertex in such a way + * that no two adjacent vertices share the same color. + * + * @param v Number of vertices in the graph + * @param adj Adjacency list of the graph where each index i contains a list of adjacent vertices + * @param color Array to store the color assigned to each vertex (-1 indicates uncolored) + * @param node Current vertex being processed + * @return True if the graph (or component of the graph) is bipartite, otherwise false + */ private static boolean bipartite(int v, ArrayList> adj, int[] color, int node) { if (color[node] == -1) { color[node] = 1; @@ -35,11 +61,16 @@ private static boolean bipartite(int v, ArrayList> adj, int[] return true; } + /** + * Method to check if the graph is bipartite. + * + * @param v Number of vertices in the graph + * @param adj Adjacency list of the graph + * @return True if the graph is bipartite, otherwise false + */ public static boolean isBipartite(int v, ArrayList> adj) { - // Code here int[] color = new int[v + 1]; Arrays.fill(color, -1); - for (int i = 0; i < v; i++) { if (color[i] == -1) { if (!bipartite(v, adj, color, i)) { @@ -49,33 +80,4 @@ public static boolean isBipartite(int v, ArrayList> adj) { } return true; } - - public static void main(String[] args) throws IOException { - BufferedReader read = new BufferedReader(new InputStreamReader(System.in)); - int t = Integer.parseInt(read.readLine().trim()); - while (t-- > 0) { - String[] str1 = read.readLine().trim().split(" "); - int numVertices = Integer.parseInt(str1[0]); - int numEdges = Integer.parseInt(str1[1]); - - ArrayList> adj = new ArrayList<>(); - for (int i = 0; i < numVertices; i++) { - adj.add(new ArrayList<>()); - } - for (int i = 0; i < numEdges; i++) { - String[] str2 = read.readLine().trim().split(" "); - int vertexU = Integer.parseInt(str2[0]); - int vertexV = Integer.parseInt(str2[1]); - adj.get(vertexU).add(vertexV); - adj.get(vertexV).add(vertexU); - } - - boolean ans = isBipartite(numVertices, adj); - if (ans) { - System.out.println("YES"); - } else { - System.out.println("NO"); - } - } - } } diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFSTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFSTest.java new file mode 100644 index 000000000000..75fa6adc3014 --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFSTest.java @@ -0,0 +1,73 @@ +package com.thealgorithms.datastructures.graphs; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import org.junit.jupiter.api.Test; + +public class BipartiteGraphDFSTest { + + // Helper method to create an adjacency list from edges + private ArrayList> createAdjacencyList(int numVertices, int[][] edges) { + ArrayList> adj = new ArrayList<>(); + for (int i = 0; i < numVertices; i++) { + adj.add(new ArrayList<>()); + } + for (int[] edge : edges) { + int vertexU = edge[0]; + int vertexV = edge[1]; + adj.get(vertexU).add(vertexV); + adj.get(vertexV).add(vertexU); + } + return adj; + } + + @Test + public void testBipartiteGraphEvenCycle() { + int numVertices = 4; + int[][] edges = {{0, 1}, {1, 2}, {2, 3}, {3, 0}}; // Even cycle + ArrayList> adj = createAdjacencyList(numVertices, edges); + assertTrue(BipartiteGraphDFS.isBipartite(numVertices, adj), "Graph should be bipartite (even cycle)"); + } + + @Test + public void testBipartiteGraphOddCycle() { + int numVertices = 5; + int[][] edges = {{0, 1}, {1, 2}, {2, 0}, {1, 3}, {3, 4}}; // Odd cycle + ArrayList> adj = createAdjacencyList(numVertices, edges); + assertFalse(BipartiteGraphDFS.isBipartite(numVertices, adj), "Graph should not be bipartite (odd cycle)"); + } + + @Test + public void testBipartiteGraphDisconnected() { + int numVertices = 6; + int[][] edges = {{0, 1}, {2, 3}, {4, 5}}; // Disconnected bipartite graphs + ArrayList> adj = createAdjacencyList(numVertices, edges); + assertTrue(BipartiteGraphDFS.isBipartite(numVertices, adj), "Graph should be bipartite (disconnected)"); + } + + @Test + public void testBipartiteGraphSingleVertex() { + int numVertices = 1; + int[][] edges = {}; // Single vertex, no edges + ArrayList> adj = createAdjacencyList(numVertices, edges); + assertTrue(BipartiteGraphDFS.isBipartite(numVertices, adj), "Graph should be bipartite (single vertex)"); + } + + @Test + public void testBipartiteGraphCompleteBipartite() { + int numVertices = 4; + int[][] edges = {{0, 2}, {0, 3}, {1, 2}, {1, 3}}; // K2,2 (Complete bipartite graph) + ArrayList> adj = createAdjacencyList(numVertices, edges); + assertTrue(BipartiteGraphDFS.isBipartite(numVertices, adj), "Graph should be bipartite (complete bipartite)"); + } + + @Test + public void testBipartiteGraphNonBipartite() { + int numVertices = 3; + int[][] edges = {{0, 1}, {1, 2}, {2, 0}}; // Triangle (odd cycle) + ArrayList> adj = createAdjacencyList(numVertices, edges); + assertFalse(BipartiteGraphDFS.isBipartite(numVertices, adj), "Graph should not be bipartite (triangle)"); + } +}