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 b30bdd3

Browse files
adi776boraterealstealthninjagithub-actions[bot]
authored
feat: add algorithm to find the number of paths in a graph using DFS (#2815)
* feat: add count_paths algorithm with a test case * fix: updated number_of_paths algorithm, added more test cases, and set unsigned int as parameter * fix: replaced unsigned int with std::uint32_t for fixed size * fix: Handled empty graph, invalid input and added test cases for the same * clang-format and clang-tidy fixes for 80e27ba --------- Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 93c64b5 commit b30bdd3

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

‎graph/number_of_paths.cpp‎

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/**
2+
* @file
3+
* @brief Algorithm to count paths between two nodes in a directed graph using DFS
4+
* @details
5+
* This algorithm implements Depth First Search (DFS) to count the number of
6+
* possible paths between two nodes in a directed graph. It is represented using
7+
* an adjacency matrix. The algorithm recursively traverses the graph to find
8+
* all paths from the source node `u` to the destination node `v`.
9+
*
10+
* @author [Aditya Borate](https://github.com/adi776borate)
11+
* @see https://en.wikipedia.org/wiki/Path_(graph_theory)
12+
*/
13+
14+
#include <vector> /// for std::vector
15+
#include <iostream> /// for IO operations
16+
#include <cassert> /// for assert
17+
#include <cstdint> /// for fixed-size integer types (e.g., std::uint32_t)
18+
19+
/**
20+
* @namespace graph
21+
* @brief Graph algorithms
22+
*/
23+
namespace graph {
24+
25+
/**
26+
* @brief Helper function to perform DFS and count the number of paths from node `u` to node `v`
27+
* @param A adjacency matrix representing the graph (1: edge exists, 0: no edge)
28+
* @param u the starting node
29+
* @param v the destination node
30+
* @param n the number of nodes in the graph
31+
* @param visited a vector to keep track of visited nodes in the current DFS path
32+
* @returns the number of paths from node `u` to node `v`
33+
*/
34+
std::uint32_t count_paths_dfs(const std::vector<std::vector<std::uint32_t>>& A,
35+
std::uint32_t u,
36+
std::uint32_t v,
37+
std::uint32_t n,
38+
std::vector<bool>& visited) {
39+
if (u == v) {
40+
return 1; // Base case: Reached the destination node
41+
}
42+
43+
visited[u] = true; // Mark the current node as visited
44+
std::uint32_t path_count = 0; // Count of all paths from `u` to `v`
45+
46+
for (std::uint32_t i = 0; i < n; i++) {
47+
if (A[u][i] == 1 && !visited[i]) { // Check if there is an edge and the node is not visited
48+
path_count += count_paths_dfs(A, i, v, n, visited); // Recursively explore paths from `i` to `v`
49+
}
50+
}
51+
52+
visited[u] = false; // Unmark the current node as visited (backtracking)
53+
return path_count;
54+
}
55+
56+
57+
/**
58+
* @brief Counts the number of paths from node `u` to node `v` in a directed graph
59+
* using Depth First Search (DFS)
60+
*
61+
* @param A adjacency matrix representing the graph (1: edge exists, 0: no edge)
62+
* @param u the starting node
63+
* @param v the destination node
64+
* @param n the number of nodes in the graph
65+
* @returns the number of paths from node `u` to node `v`
66+
*/
67+
std::uint32_t count_paths(const std::vector<std::vector<std::uint32_t>>& A,
68+
std::uint32_t u,
69+
std::uint32_t v,
70+
std::uint32_t n) {
71+
// Check for invalid nodes or empty graph
72+
if (u >= n || v >= n || A.empty() || A[0].empty()) {
73+
return 0; // No valid paths if graph is empty or nodes are out of bounds
74+
}
75+
76+
std::vector<bool> visited(n, false); // Initialize a visited vector for tracking nodes
77+
return count_paths_dfs(A, u, v, n, visited); // Start DFS
78+
}
79+
80+
} // namespace graph
81+
82+
/**
83+
* @brief Self-test implementations
84+
* @returns void
85+
*/
86+
static void test() {
87+
// Test case 1: Simple directed graph with multiple paths
88+
std::vector<std::vector<std::uint32_t>> graph1 = {
89+
{0, 1, 0, 1, 0},
90+
{0, 0, 1, 0, 1},
91+
{0, 0, 0, 0, 1},
92+
{0, 0, 1, 0, 0},
93+
{0, 0, 0, 0, 0}
94+
};
95+
std::uint32_t n1 = 5, u1 = 0, v1 = 4;
96+
assert(graph::count_paths(graph1, u1, v1, n1) == 3); // There are 3 paths from node 0 to 4
97+
98+
// Test case 2: No possible path (disconnected graph)
99+
std::vector<std::vector<std::uint32_t>> graph2 = {
100+
{0, 1, 0, 0, 0},
101+
{0, 0, 0, 0, 0},
102+
{0, 0, 0, 0, 1},
103+
{0, 0, 1, 0, 0},
104+
{0, 0, 0, 0, 0}
105+
};
106+
std::uint32_t n2 = 5, u2 = 0, v2 = 4;
107+
assert(graph::count_paths(graph2, u2, v2, n2) == 0); // No path from node 0 to 4
108+
109+
// Test case 3: Cyclic graph with multiple paths
110+
std::vector<std::vector<std::uint32_t>> graph3 = {
111+
{0, 1, 0, 0, 0},
112+
{0, 0, 1, 1, 0},
113+
{1, 0, 0, 0, 1},
114+
{0, 0, 1, 0, 1},
115+
{0, 0, 0, 0, 0}
116+
};
117+
std::uint32_t n3 = 5, u3 = 0, v3 = 4;
118+
assert(graph::count_paths(graph3, u3, v3, n3) == 3); // There are 3 paths from node 0 to 4
119+
120+
// Test case 4: Single node graph (self-loop)
121+
std::vector<std::vector<std::uint32_t>> graph4 = {
122+
{0}
123+
};
124+
std::uint32_t n4 = 1, u4 = 0, v4 = 0;
125+
assert(graph::count_paths(graph4, u4, v4, n4) == 1); // There is self-loop, so 1 path from node 0 to 0
126+
127+
// Test case 5: Empty graph (no nodes, no paths)
128+
std::vector<std::vector<std::uint32_t>> graph5 = {{}};
129+
int n5 = 0, u5 = 0, v5 = 0;
130+
assert(graph::count_paths(graph5, u5, v5, n5) == 0); // There are no paths in an empty graph
131+
132+
// Test case 6: Invalid nodes (out of bounds)
133+
std::vector<std::vector<std::uint32_t>> graph6 = {
134+
{0, 1, 0},
135+
{0, 0, 1},
136+
{0, 0, 0}
137+
};
138+
int n6 = 3, u6 = 0, v6 = 5; // Node `v` is out of bounds (n = 3, so valid indices are 0, 1, 2)
139+
assert(graph::count_paths(graph6, u6, v6, n6) == 0); // Should return 0 because `v = 5` is invalid
140+
141+
std::cout << "All tests have successfully passed!\n";
142+
}
143+
144+
/**
145+
* @brief Main function
146+
* @returns 0 on exit
147+
*/
148+
int main() {
149+
test(); // Run self-test implementations
150+
return 0;
151+
}

0 commit comments

Comments
(0)

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