diff --git a/src/main/java/com/thealgorithms/graph/ConstrainedShortestPath.java b/src/main/java/com/thealgorithms/graph/ConstrainedShortestPath.java
new file mode 100644
index 000000000000..f397989911d9
--- /dev/null
+++ b/src/main/java/com/thealgorithms/graph/ConstrainedShortestPath.java
@@ -0,0 +1,123 @@
+package com.thealgorithms.graph;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This class implements a solution for the Constrained Shortest Path Problem (CSPP).
+ * also known as Shortest Path Problem with Resource Constraints (SPPRC).
+ * The goal is to find the shortest path between two nodes while ensuring that
+ * the resource constraint is not exceeded.
+ *
+ * @author Deniz Altunkapan
+ */
+public class ConstrainedShortestPath {
+
+ /**
+ * Represents a graph using an adjacency list.
+ * This graph is designed for the Constrained Shortest Path Problem (CSPP).
+ */
+ public static class Graph {
+
+ private List> adjacencyList;
+
+ public Graph(int numNodes) {
+ adjacencyList = new ArrayList<>();
+ for (int i = 0; i < numNodes; i++) {
+ adjacencyList.add(new ArrayList<>());
+ }
+ }
+
+ /**
+ * Adds an edge to the graph.
+ * @param from the starting node
+ * @param to the ending node
+ * @param cost the cost of the edge
+ * @param resource the resource required to traverse the edge
+ */
+ public void addEdge(int from, int to, int cost, int resource) {
+ adjacencyList.get(from).add(new Edge(from, to, cost, resource));
+ }
+
+ /**
+ * Gets the edges that are adjacent to a given node.
+ * @param node the node to get the edges for
+ * @return the list of edges adjacent to the node
+ */
+ public List getEdges(int node) {
+ return adjacencyList.get(node);
+ }
+
+ /**
+ * Gets the number of nodes in the graph.
+ * @return the number of nodes
+ */
+ public int getNumNodes() {
+ return adjacencyList.size();
+ }
+
+ public record Edge(int from, int to, int cost, int resource) {
+ }
+ }
+
+ private Graph graph;
+ private int maxResource;
+
+ /**
+ * Constructs a CSPSolver with the given graph and maximum resource constraint.
+ *
+ * @param graph the graph representing the problem
+ * @param maxResource the maximum allowable resource
+ */
+ public ConstrainedShortestPath(Graph graph, int maxResource) {
+ this.graph = graph;
+ this.maxResource = maxResource;
+ }
+
+ /**
+ * Solves the CSP to find the shortest path from the start node to the target node
+ * without exceeding the resource constraint.
+ *
+ * @param start the starting node
+ * @param target the target node
+ * @return the minimum cost to reach the target node within the resource constraint,
+ * or -1 if no valid path exists
+ */
+ public int solve(int start, int target) {
+ int numNodes = graph.getNumNodes();
+ int[][] dp = new int[maxResource + 1][numNodes];
+
+ // Initialize dp table with maximum values
+ for (int i = 0; i <= maxResource; i++) {
+ Arrays.fill(dp[i], Integer.MAX_VALUE);
+ }
+ dp[0][start] = 0;
+
+ // Dynamic Programming: Iterate over resources and nodes
+ for (int r = 0; r <= maxResource; r++) {
+ for (int u = 0; u < numNodes; u++) {
+ if (dp[r][u] == Integer.MAX_VALUE) {
+ continue;
+ }
+ for (Graph.Edge edge : graph.getEdges(u)) {
+ int v = edge.to();
+ int cost = edge.cost();
+ int resource = edge.resource();
+
+ if (r + resource <= maxResource) {
+ dp[r + resource][v] = Math.min(dp[r + resource][v], dp[r][u] + cost);
+ }
+ }
+ }
+ }
+
+ // Find the minimum cost to reach the target node
+ int minCost = Integer.MAX_VALUE;
+ for (int r = 0; r <= maxResource; r++) {
+ minCost = Math.min(minCost, dp[r][target]);
+ }
+
+ return minCost == Integer.MAX_VALUE ? -1 : minCost;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/graph/ConstrainedShortestPathTest.java b/src/test/java/com/thealgorithms/graph/ConstrainedShortestPathTest.java
new file mode 100644
index 000000000000..eccd359f2634
--- /dev/null
+++ b/src/test/java/com/thealgorithms/graph/ConstrainedShortestPathTest.java
@@ -0,0 +1,218 @@
+package com.thealgorithms.graph;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.thealgorithms.graph.ConstrainedShortestPath.Graph;
+import org.junit.jupiter.api.Test;
+
+public class ConstrainedShortestPathTest {
+
+ /**
+ * Tests a simple linear graph to verify if the solver calculates the shortest path correctly.
+ * Expected: The minimal path cost from node 0 to node 2 should be 5 while not exceeding the resource limit.
+ */
+ @Test
+ public void testSimpleGraph() {
+ Graph graph = new Graph(3);
+ graph.addEdge(0, 1, 2, 3);
+ graph.addEdge(1, 2, 3, 2);
+
+ int maxResource = 5;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(5, solver.solve(0, 2));
+ }
+
+ /**
+ * Tests a graph where no valid path exists due to resource constraints.
+ * Expected: The solver should return -1, indicating no path is feasible.
+ */
+ @Test
+ public void testNoPath() {
+ Graph graph = new Graph(3);
+ graph.addEdge(0, 1, 2, 6);
+ graph.addEdge(1, 2, 3, 6);
+
+ int maxResource = 5;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(-1, solver.solve(0, 2));
+ }
+
+ /**
+ * Tests a graph with multiple paths between source and destination.
+ * Expected: The solver should choose the path with the minimal cost of 5, considering the resource limit.
+ */
+ @Test
+ public void testMultiplePaths() {
+ Graph graph = new Graph(4);
+ graph.addEdge(0, 1, 1, 1);
+ graph.addEdge(1, 3, 5, 2);
+ graph.addEdge(0, 2, 2, 1);
+ graph.addEdge(2, 3, 3, 2);
+
+ int maxResource = 3;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(5, solver.solve(0, 3));
+ }
+
+ /**
+ * Verifies that the solver allows a path exactly matching the resource limit.
+ * Expected: The path is valid with a total cost of 5.
+ */
+ @Test
+ public void testExactResourceLimit() {
+ Graph graph = new Graph(3);
+ graph.addEdge(0, 1, 2, 3);
+ graph.addEdge(1, 2, 3, 2);
+
+ int maxResource = 5;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(5, solver.solve(0, 2));
+ }
+
+ /**
+ * Tests a disconnected graph where the destination node cannot be reached.
+ * Expected: The solver should return -1, as the destination is unreachable.
+ */
+ @Test
+ public void testDisconnectedGraph() {
+ Graph graph = new Graph(4);
+ graph.addEdge(0, 1, 2, 2);
+ graph.addEdge(2, 3, 3, 2);
+
+ int maxResource = 5;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(-1, solver.solve(0, 3));
+ }
+
+ /**
+ * Tests a graph with cycles to ensure the solver does not fall into infinite loops and correctly calculates costs.
+ * Expected: The solver should compute the minimal path cost of 6.
+ */
+ @Test
+ public void testGraphWithCycles() {
+ Graph graph = new Graph(4);
+ graph.addEdge(0, 1, 2, 1);
+ graph.addEdge(1, 2, 3, 1);
+ graph.addEdge(2, 0, 1, 1);
+ graph.addEdge(1, 3, 4, 2);
+
+ int maxResource = 3;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(6, solver.solve(0, 3));
+ }
+
+ /**
+ * Tests the solver's performance and correctness on a large linear graph with 1000 nodes.
+ * Expected: The solver should efficiently calculate the shortest path with a cost of 999.
+ */
+ @Test
+ public void testLargeGraphPerformance() {
+ int nodeCount = 1000;
+ Graph graph = new Graph(nodeCount);
+ for (int i = 0; i < nodeCount - 1; i++) {
+ graph.addEdge(i, i + 1, 1, 1);
+ }
+
+ int maxResource = 1000;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(999, solver.solve(0, nodeCount - 1));
+ }
+
+ /**
+ * Tests a graph with isolated nodes to ensure the solver recognizes unreachable destinations.
+ * Expected: The solver should return -1 for unreachable nodes.
+ */
+ @Test
+ public void testIsolatedNodes() {
+ Graph graph = new Graph(5);
+ graph.addEdge(0, 1, 2, 1);
+ graph.addEdge(1, 2, 3, 1);
+
+ int maxResource = 5;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(-1, solver.solve(0, 3));
+ }
+
+ /**
+ * Tests a cyclic large graph with multiple overlapping paths.
+ * Expected: The solver should calculate the shortest path cost of 5.
+ */
+ @Test
+ public void testCyclicLargeGraph() {
+ Graph graph = new Graph(10);
+ for (int i = 0; i < 9; i++) {
+ graph.addEdge(i, (i + 1) % 10, 1, 1);
+ }
+ graph.addEdge(0, 5, 5, 3);
+
+ int maxResource = 10;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(5, solver.solve(0, 5));
+ }
+
+ /**
+ * Tests a large complex graph with multiple paths and varying resource constraints.
+ * Expected: The solver should identify the optimal path with a cost of 19 within the resource limit.
+ */
+ @Test
+ public void testLargeComplexGraph() {
+ Graph graph = new Graph(10);
+ graph.addEdge(0, 1, 4, 2);
+ graph.addEdge(0, 2, 3, 3);
+ graph.addEdge(1, 3, 2, 1);
+ graph.addEdge(2, 3, 5, 2);
+ graph.addEdge(2, 4, 8, 4);
+ graph.addEdge(3, 5, 7, 3);
+ graph.addEdge(3, 6, 6, 2);
+ graph.addEdge(4, 6, 3, 2);
+ graph.addEdge(5, 7, 1, 1);
+ graph.addEdge(6, 7, 2, 2);
+ graph.addEdge(7, 8, 3, 1);
+ graph.addEdge(8, 9, 2, 1);
+
+ int maxResource = 10;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(19, solver.solve(0, 9));
+ }
+
+ /**
+ * Edge case test where the graph has only one node and no edges.
+ * Expected: The minimal path cost is 0, as the start and destination are the same.
+ */
+ @Test
+ public void testSingleNodeGraph() {
+ Graph graph = new Graph(1);
+
+ int maxResource = 0;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(0, solver.solve(0, 0));
+ }
+
+ /**
+ * Tests a graph with multiple paths but a tight resource constraint.
+ * Expected: The solver should return -1 if no path can be found within the resource limit.
+ */
+ @Test
+ public void testTightResourceConstraint() {
+ Graph graph = new Graph(4);
+ graph.addEdge(0, 1, 3, 4);
+ graph.addEdge(1, 2, 1, 2);
+ graph.addEdge(0, 2, 2, 2);
+
+ int maxResource = 3;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(2, solver.solve(0, 2));
+ }
+}