diff --git a/src/main/java/com/thealgorithms/graph/ZeroOneBfs.java b/src/main/java/com/thealgorithms/graph/ZeroOneBfs.java
new file mode 100644
index 000000000000..53181a654215
--- /dev/null
+++ b/src/main/java/com/thealgorithms/graph/ZeroOneBfs.java
@@ -0,0 +1,77 @@
+package com.thealgorithms.graph;
+
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.List;
+
+/**
+ * 0-1 BFS for shortest paths on graphs with edges weighted 0 or 1.
+ *
+ *
Time Complexity: O(V + E). Space Complexity: O(V).
+ *
+ *
References:
+ *
+ * - https://cp-algorithms.com/graph/01_bfs.html
+ *
+ */
+public final class ZeroOneBfs {
+
+ private ZeroOneBfs() {
+ // Utility class; do not instantiate.
+ }
+
+ /**
+ * Computes shortest distances from {@code src} in a graph whose edges have weight 0 or 1.
+ *
+ * @param n the number of vertices, labeled {@code 0..n-1}
+ * @param adj adjacency list; for each vertex u, {@code adj.get(u)} is a list of pairs
+ * {@code (v, w)} where {@code v} is a neighbor and {@code w} is 0 or 1
+ * @param src the source vertex
+ * @return an array of distances; {@code Integer.MAX_VALUE} denotes unreachable
+ * @throws IllegalArgumentException if {@code n < 0}, {@code src} is out of range,
+ * or any edge has weight other than 0 or 1
+ */
+ public static int[] shortestPaths(int n, List> adj, int src) {
+ if (n < 0 || src < 0 || src >= n) {
+ throw new IllegalArgumentException("Invalid n or src");
+ }
+ int[] dist = new int[n];
+ Arrays.fill(dist, Integer.MAX_VALUE);
+ Deque dq = new ArrayDeque<>();
+
+ dist[src] = 0;
+ dq.addFirst(src);
+
+ while (!dq.isEmpty()) {
+ int u = dq.pollFirst();
+ List edges = adj.get(u);
+ if (edges == null) {
+ continue;
+ }
+ for (int[] e : edges) {
+ if (e == null || e.length < 2) {
+ continue;
+ }
+ int v = e[0];
+ int w = e[1];
+ if (v < 0 || v >= n) {
+ continue; // ignore bad edges
+ }
+ if (w != 0 && w != 1) {
+ throw new IllegalArgumentException("Edge weight must be 0 or 1");
+ }
+ int nd = dist[u] + w;
+ if (nd < dist[v]) {
+ dist[v] = nd;
+ if (w == 0) {
+ dq.addFirst(v);
+ } else {
+ dq.addLast(v);
+ }
+ }
+ }
+ }
+ return dist;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/graph/ZeroOneBfsTest.java b/src/test/java/com/thealgorithms/graph/ZeroOneBfsTest.java
new file mode 100644
index 000000000000..5de9eadf0930
--- /dev/null
+++ b/src/test/java/com/thealgorithms/graph/ZeroOneBfsTest.java
@@ -0,0 +1,68 @@
+package com.thealgorithms.graph;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+class ZeroOneBfsTest {
+
+ // Helper to build adjacency list with capacity n
+ private static List> makeAdj(int n) {
+ List> adj = new ArrayList<>(n);
+ for (int i = 0; i < n; i++) {
+ adj.add(new ArrayList<>());
+ }
+ return adj;
+ }
+
+ @Test
+ void simpleLineGraph() {
+ int n = 4;
+ List> adj = makeAdj(n);
+ // 0 --0--> 1 --1--> 2 --0--> 3
+ adj.get(0).add(new int[] {1, 0});
+ adj.get(1).add(new int[] {2, 1});
+ adj.get(2).add(new int[] {3, 0});
+
+ int[] dist = ZeroOneBfs.shortestPaths(n, adj, 0);
+ assertArrayEquals(new int[] {0, 0, 1, 1}, dist);
+ }
+
+ @Test
+ void parallelEdgesPreferZero() {
+ int n = 3;
+ List> adj = makeAdj(n);
+ // Two edges 0->1: weight 1 and weight 0. Algorithm should choose 0.
+ adj.get(0).add(new int[] {1, 1});
+ adj.get(0).add(new int[] {1, 0});
+ adj.get(1).add(new int[] {2, 1});
+
+ int[] dist = ZeroOneBfs.shortestPaths(n, adj, 0);
+ assertArrayEquals(new int[] {0, 0, 1}, dist);
+ }
+
+ @Test
+ void unreachableNodes() {
+ int n = 3;
+ List> adj = makeAdj(n);
+ adj.get(0).add(new int[] {1, 0});
+ int[] dist = ZeroOneBfs.shortestPaths(n, adj, 0);
+ // node 2 unreachable -> Integer.MAX_VALUE
+ assertArrayEquals(new int[] {0, 0, Integer.MAX_VALUE}, dist);
+ }
+
+ @Test
+ void invalidArgs() {
+ int n = 2;
+ List> adj = makeAdj(n);
+ // invalid weight
+ adj.get(0).add(new int[] {1, 2});
+ assertThrows(IllegalArgumentException.class, () -> ZeroOneBfs.shortestPaths(n, adj, 0));
+ // invalid src
+ assertThrows(IllegalArgumentException.class, () -> ZeroOneBfs.shortestPaths(n, adj, -1));
+ assertThrows(IllegalArgumentException.class, () -> ZeroOneBfs.shortestPaths(n, adj, 2));
+ }
+}