Count All Paths Between Two Vertices

Last Updated : 1 Jul, 2026

Given a Directed Acyclic Graph (DAG) with V vertices (numbered 0 to V-1) and a list of directed edges edges[][], where each edges[i] = [u, v] represents a directed edge from vertex u to vertex v. Given two vertices src and dest, find the total number of distinct paths from src to dest.

Note: The graph has no self-loops or multiple edges.

Examples:

Input: V = 5, edges[][] = [[0, 1], [0, 2], [0, 4], [1, 3], [1, 4], [2, 4], [3, 2]], src = 0, dest = 4
Output: 4
Explanation: There are 4 paths from 0 to 4.
0 -> 4
0 -> 1 -> 4
0 -> 2 -> 4
0 -> 1 -> 3 -> 2 -> 4

blobid0_1752143630

Input: V = 4, edges[][] = [[0, 1], [0, 3], [1, 2], [1, 3], [2, 3]], src = 0, dest = 3
Output: 3
Explanation: There are 3 paths from 0 to 3.
0 -> 3
0 -> 1 -> 3
0 -> 1 -> 2 -> 3

2
Try It Yourself
redirect icon

What happens if the graph has a cycle ?

Frame-3352

Consider above graph, with src = 0 and dest = 4, nodes 1, 2, and 3 form a cycle (1 -> 2 -> 3 -> 1), and 3 also has an exit edge to 4. At 3, the path can either exit to 4 or loop back through the cycle first.

This gives 0 -> 1 -> 2 -> 3 -> 4 (no loop), 0 -> 1 -> 2 -> 3 -> 1 -> 2 -> 3 -> 4 (one loop), and so on indefinitely - each loop produces one more valid path. So the path count is infinite whenever a cycle offers a repeatable choice to loop or exit toward dest, which is exactly why the problem requires the graph to be acyclic.

[Naive Approach] Using DFS Traversal - O(2 ^ V) Time and O(V) Space

The idea is to start a DFS from src and explore all possible paths to dest. Whenever dest is reached, count it as one valid path. Since the graph is a DAG, a vertex can be reached through multiple different paths, causing the same subproblems to be recomputed many times. As a result, the number of recursive calls can grow exponentially in the number of vertices.

Step by Step Implementation:

  • Build an adjacency list from the given edges.
  • Start a DFS traversal from src.
  • If the current vertex is dest, return 1.
  • Recursively explore all outgoing neighbors.
  • Sum the number of paths returned by each recursive call.
  • Return the total count of paths from src to dest.
C++
#include <iostream>
#include <vector>
using namespace std;

int dfs(int u, int dest, vector<vector<int>>& adj) {

    // Reached destination.
    if (u == dest)
        return 1;

    int paths = 0;

    for (int v : adj[u])
        paths += dfs(v, dest, adj);

    return paths;
}

int countPaths(int V, vector<vector<int>>& edges, int src, int dest) {

    vector<vector<int>> adj(V);

    for (auto& e : edges)
        adj[e[0]].push_back(e[1]);

    return dfs(src, dest, adj);
}

int main() {

    int V = 5;

    vector<vector<int>> edges = {
        {0, 1}, {0, 2}, {0, 4},
        {1, 3}, {1, 4},
        {2, 4},
        {3, 2}
    };

    int src = 0, dest = 4;

    cout << countPaths(V, edges, src, dest);

    return 0;
}
Java
import java.util.ArrayList;

class GFG {

    static int dfs(int u, int dest, ArrayList<Integer>[] adj) {

        // Reached destination.
        if (u == dest)
            return 1;

        int paths = 0;

        for (int v : adj[u])
            paths += dfs(v, dest, adj);

        return paths;
    }

    static int countPaths(int V, int[][] edges, int src, int dest) {

        ArrayList<Integer>[] adj = new ArrayList[V];

        for (int i = 0; i < V; i++)
            adj[i] = new ArrayList<>();

        for (int[] e : edges)
            adj[e[0]].add(e[1]);

        return dfs(src, dest, adj);
    }

    public static void main(String[] args) {

        int V = 5;

        int[][] edges = {
            {0, 1}, {0, 2}, {0, 4},
            {1, 3}, {1, 4},
            {2, 4},
            {3, 2}
        };

        int src = 0, dest = 4;

        System.out.println(countPaths(V, edges, src, dest));
    }
}
Python
def dfs(u, dest, adj):

    # Reached destination.
    if u == dest:
        return 1

    paths = 0

    for v in adj[u]:
        paths += dfs(v, dest, adj)

    return paths


def countPaths(V, edges, src, dest):

    adj = [[] for _ in range(V)]

    for u, v in edges:
        adj[u].append(v)

    return dfs(src, dest, adj)


V = 5

edges = [
    [0, 1], [0, 2], [0, 4],
    [1, 3], [1, 4],
    [2, 4],
    [3, 2]
]

src, dest = 0, 4

print(countPaths(V, edges, src, dest))
C#
using System;
using System.Collections.Generic;

class GFG {

    static int Dfs(int u, int dest, List<int>[] adj) {

        // Reached destination.
        if (u == dest)
            return 1;

        int paths = 0;

        foreach (int v in adj[u])
            paths += Dfs(v, dest, adj);

        return paths;
    }

    static int countPaths(int V, int[,] edges, int src, int dest) {

        List<int>[] adj = new List<int>[V];

        for (int i = 0; i < V; i++)
            adj[i] = new List<int>();

        for (int i = 0; i < edges.GetLength(0); i++)
            adj[edges[i, 0]].Add(edges[i, 1]);

        return Dfs(src, dest, adj);
    }

    static void Main() {

        int V = 5;

        int[,] edges = {
            {0, 1}, {0, 2}, {0, 4},
            {1, 3}, {1, 4},
            {2, 4},
            {3, 2}
        };

        int src = 0, dest = 4;

        Console.WriteLine(countPaths(V, edges, src, dest));
    }
}
JavaScript
function dfs(u, dest, adj) {

    // Reached destination.
    if (u === dest)
        return 1;

    let paths = 0;

    for (const v of adj[u])
        paths += dfs(v, dest, adj);

    return paths;
}

function countPaths(V, edges, src, dest) {

    const adj = Array.from({ length: V }, () => []);

    for (const [u, v] of edges)
        adj[u].push(v);

    return dfs(src, dest, adj);
}

// Driver Code
const V = 5;

const edges = [
    [0, 1], [0, 2], [0, 4],
    [1, 3], [1, 4],
    [2, 4],
    [3, 2]
];

const src = 0, dest = 4;

console.log(countPaths(V, edges, src, dest));

Output
4

[Expected Approach 1] Using DFS and Memoization - O(V + E) Time and O(V + E) Space

The idea is to use DFS to count the number of paths from a vertex to dest. Since the graph is a DAG, the number of paths from a vertex remains the same whenever it is revisited. Therefore, we store the computed result for each vertex in a visited array and reuse it whenever needed. This avoids recomputing the same subproblems multiple times and allows each vertex to be processed only once.

Step By Step Implementation:

  • Build an adjacency list from the given edges.
  • Create a visited array initialized with -1 to store computed path counts.
  • Start a DFS traversal from src.
  • If the current vertex is dest, return 1.
  • If the result for the current vertex is already computed, return it.
  • Recursively count paths through all outgoing neighbors.
  • Store the computed count in the visited array.
  • Return the number of paths from src to dest.
C++
#include <bits/stdc++.h>
using namespace std;

int dfs(int u, int dest, vector<vector<int>>& adj, 
        vector<int>& visited) {
    if (u == dest) return 1;
    if (visited[u]!= -1) return visited[u];

    int total = 0;
    for (int v : adj[u]) {
        total += dfs(v, dest, adj, visited);
    }

    return visited[u] = total;
}

int countPaths(int V, vector<vector<int>>& edges, int src, int dest) {
    vector<vector<int>> adj(V);
    for (auto& e : edges) adj[e[0]].push_back(e[1]);

    // visited[u] stores the number of paths from u to dest, once computed
    vector<int> visited(V, -1);

    return dfs(src, dest, adj, visited);
}

int main() {
    int V = 5;
    vector<vector<int>> edges = {{0,1},{0,2},{0,4},{1,3},{1,4},{2,4},{3,2}};
    int src = 0, dest = 4;

    cout << countPaths(V, edges, src, dest) << endl;
    return 0;
}
Java
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;

class GFG {
    static int dfs(int u, int dest, List<List<Integer>> adj, int[] visited) {
        if (u == dest) return 1;
        if (visited[u] != -1) return visited[u];

        int total = 0;
        for (int v : adj.get(u)) {
            total += dfs(v, dest, adj, visited);
        }

        visited[u] = total;
        return total;
    }

    static int countPaths(int V, int[][] edges, int src, int dest) {
        List<List<Integer>> adj = new ArrayList<>();
        for (int i = 0; i < V; i++) adj.add(new ArrayList<>());
        for (int[] e : edges) adj.get(e[0]).add(e[1]);

        // visited[u] stores the number of paths from u to dest, once computed
        int[] visited = new int[V];
        Arrays.fill(visited, -1);

        return dfs(src, dest, adj, visited);
    }

    public static void main(String[] args) {
        int V = 5;
        int[][] edges = {{0,1},{0,2},{0,4},{1,3},{1,4},{2,4},{3,2}};
        int src = 0, dest = 4;

        System.out.println(countPaths(V, edges, src, dest));
    }
}
Python
def dfs(u, dest, adj, visited):
    if u == dest:
        return 1
    if visited[u] != -1:
        return visited[u]

    total = 0
    for v in adj[u]:
        total += dfs(v, dest, adj, visited)

    visited[u] = total
    return total

def countPaths(V, edges, src, dest):
    adj = [[] for _ in range(V)]
    for u, v in edges:
        adj[u].append(v)

    # visited[u] stores the number of paths from u to dest, once computed
    visited = [-1] * V

    return dfs(src, dest, adj, visited)

V = 5
edges = [[0,1],[0,2],[0,4],[1,3],[1,4],[2,4],[3,2]]
src, dest = 0, 4

print(countPaths(V, edges, src, dest))
C#
using System;
using System.Collections.Generic;

class GFG {
    static int Dfs(int u, int dest, List<int>[] adj, int[] visited) {
        if (u == dest) return 1;
        if (visited[u] != -1) return visited[u];

        int total = 0;
        foreach (int v in adj[u]) {
            total += Dfs(v, dest, adj, visited);
        }

        visited[u] = total;
        return total;
    }

    static int countPaths(int V, int[][] edges, int src, int dest) {
        List<int>[] adj = new List<int>[V];
        for (int i = 0; i < V; i++) adj[i] = new List<int>();
        foreach (int[] e in edges) adj[e[0]].Add(e[1]);

        // visited[u] stores the number of paths from u to dest, once computed
        int[] visited = new int[V];
        for (int i = 0; i < V; i++) visited[i] = -1;

        return Dfs(src, dest, adj, visited);
    }

    static void Main() {
        int V = 5;
        int[][] edges = { new int[]{0,1}, new int[]{0,2}, new int[]{0,4}, new int[]{1,3}, new int[]{1,4}, new int[]{2,4}, new int[]{3,2} };
        int src = 0, dest = 4;

        Console.WriteLine(countPaths(V, edges, src, dest));
    }
}
JavaScript
function dfs(u, dest, adj, visited) {
    if (u === dest) return 1;
    if (visited[u] !== -1) return visited[u];

    let total = 0;
    for (const v of adj[u]) {
        total += dfs(v, dest, adj, visited);
    }

    visited[u] = total;
    return total;
}

function countPaths(V, edges, src, dest) {
    const adj = Array.from({ length: V }, () => []);
    for (const [u, v] of edges) adj[u].push(v);

    // visited[u] stores the number of paths from u to dest, once computed
    const visited = new Array(V).fill(-1);

    return dfs(src, dest, adj, visited);
}

// Driver Code
const V = 5;
const edges = [[0,1],[0,2],[0,4],[1,3],[1,4],[2,4],[3,2]];
const src = 0, dest = 4;

console.log(countPaths(V, edges, src, dest));

Output
4

[Expected Approach 2] Using Topological Sort and Dynamic Programming - O(V + E) Time and O(V + E) Space

The idea is to process the vertices in topological order. Since all edges in a DAG go from an earlier vertex to a later vertex in the topological ordering, the number of paths from a vertex can be computed using the path counts of its outgoing neighbors. We initialize the destination vertex with one path to itself and propagate path counts in reverse topological order to compute the answer for all vertices.

Step by Step Implementation:

  • Build the adjacency list and compute the indegree of every vertex.
  • Use Kahn's Algorithm to obtain a topological ordering of the vertices.
  • Create a DP array and initialize dp[dest] = 1.
  • Traverse the topological order in reverse.
  • For each vertex, add the path counts of all its outgoing neighbors.
  • Store the result in the DP array.
  • Return dp[src] as the total number of paths from src to dest.
C++
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

int countPaths(int V, vector<vector<int>>& edges,
               int src, int dest) {

    vector<vector<int>> adj(V);
    vector<int> indegree(V, 0);

    for (auto& e : edges) {
        adj[e[0]].push_back(e[1]);
        indegree[e[1]]++;
    }

    queue<int> q;
    vector<int> topo;

    for (int i = 0; i < V; i++) {
        if (indegree[i] == 0)
            q.push(i);
    }

    while (!q.empty()) {
        int u = q.front();
        q.pop();

        topo.push_back(u);

        for (int v : adj[u]) {
            if (--indegree[v] == 0)
                q.push(v);
        }
    }

    vector<int> dp(V, 0);

    dp[dest] = 1;

    for (int i = topo.size() - 1; i >= 0; i--) {
        int u = topo[i];

        for (int v : adj[u])
            dp[u] += dp[v];
    }

    return dp[src];
}

int main() {

    int V = 5;

    vector<vector<int>> edges = {
        {0, 1}, {0, 2}, {0, 4},
        {1, 3}, {1, 4},
        {2, 4},
        {3, 2}
    };

    int src = 0, dest = 4;

    cout << countPaths(V, edges, src, dest);

    return 0;
}
Java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

class GFG {

    static int countPaths(int V, int[][] edges,
                          int src, int dest) {

        ArrayList<Integer>[] adj = new ArrayList[V];

        for (int i = 0; i < V; i++)
            adj[i] = new ArrayList<>();

        int[] indegree = new int[V];

        for (int[] e : edges) {
            adj[e[0]].add(e[1]);
            indegree[e[1]]++;
        }

        Queue<Integer> q = new LinkedList<>();
        ArrayList<Integer> topo = new ArrayList<>();

        for (int i = 0; i < V; i++) {
            if (indegree[i] == 0)
                q.offer(i);
        }

        while (!q.isEmpty()) {
            int u = q.poll();

            topo.add(u);

            for (int v : adj[u]) {
                if (--indegree[v] == 0)
                    q.offer(v);
            }
        }

        int[] dp = new int[V];

        dp[dest] = 1;

        for (int i = topo.size() - 1; i >= 0; i--) {
            int u = topo.get(i);

            for (int v : adj[u])
                dp[u] += dp[v];
        }

        return dp[src];
    }

    public static void main(String[] args) {

        int V = 5;

        int[][] edges = {
            {0, 1}, {0, 2}, {0, 4},
            {1, 3}, {1, 4},
            {2, 4},
            {3, 2}
        };

        int src = 0, dest = 4;

        System.out.println(countPaths(V, edges, src, dest));
    }
}
Python
from collections import deque

def countPaths(V, edges, src, dest):

    adj = [[] for _ in range(V)]
    indegree = [0] * V

    for u, v in edges:
        adj[u].append(v)
        indegree[v] += 1

    q = deque()
    topo = []

    for i in range(V):
        if indegree[i] == 0:
            q.append(i)

    while q:
        u = q.popleft()

        topo.append(u)

        for v in adj[u]:
            indegree[v] -= 1

            if indegree[v] == 0:
                q.append(v)

    dp = [0] * V

    dp[dest] = 1

    for u in reversed(topo):
        for v in adj[u]:
            dp[u] += dp[v]

    return dp[src]


V = 5

edges = [
    [0, 1], [0, 2], [0, 4],
    [1, 3], [1, 4],
    [2, 4],
    [3, 2]
]

src, dest = 0, 4

print(countPaths(V, edges, src, dest))
C#
using System;
using System.Collections.Generic;

class GFG {

    static int countPaths(int V, int[,] edges,
                          int src, int dest) {

        List<int>[] adj = new List<int>[V];

        for (int i = 0; i < V; i++)
            adj[i] = new List<int>();

        int[] indegree = new int[V];

        for (int i = 0; i < edges.GetLength(0); i++) {
            adj[edges[i, 0]].Add(edges[i, 1]);
            indegree[edges[i, 1]]++;
        }

        Queue<int> q = new Queue<int>();
        List<int> topo = new List<int>();

        for (int i = 0; i < V; i++) {
            if (indegree[i] == 0)
                q.Enqueue(i);
        }

        while (q.Count > 0) {
            int u = q.Dequeue();

            topo.Add(u);

            foreach (int v in adj[u]) {
                if (--indegree[v] == 0)
                    q.Enqueue(v);
            }
        }

        int[] dp = new int[V];

        dp[dest] = 1;

        for (int i = topo.Count - 1; i >= 0; i--) {
            int u = topo[i];

            foreach (int v in adj[u])
                dp[u] += dp[v];
        }

        return dp[src];
    }

    static void Main() {

        int V = 5;

        int[,] edges = {
            {0, 1}, {0, 2}, {0, 4},
            {1, 3}, {1, 4},
            {2, 4},
            {3, 2}
        };

        int src = 0, dest = 4;

        Console.WriteLine(countPaths(V, edges, src, dest));
    }
}
JavaScript
function countPaths(V, edges, src, dest) {

    const adj = Array.from({ length: V }, () => []);
    const indegree = new Array(V).fill(0);

    for (const [u, v] of edges) {
        adj[u].push(v);
        indegree[v]++;
    }

    const q = [];
    const topo = [];

    for (let i = 0; i < V; i++) {
        if (indegree[i] === 0)
            q.push(i);
    }

    let front = 0;

    while (front < q.length) {
        const u = q[front++];

        topo.push(u);

        for (const v of adj[u]) {
            if (--indegree[v] === 0)
                q.push(v);
        }
    }

    const dp = new Array(V).fill(0);

    dp[dest] = 1;

    for (let i = topo.length - 1; i >= 0; i--) {
        const u = topo[i];

        for (const v of adj[u])
            dp[u] += dp[v];
    }

    return dp[src];
}

// Driver Code
const V = 5;

const edges = [
    [0, 1], [0, 2], [0, 4],
    [1, 3], [1, 4],
    [2, 4],
    [3, 2]
];

const src = 0, dest = 4;

console.log(countPaths(V, edges, src, dest));

Output
4
Comment