Open In App

Number of paths from source to destination in a directed acyclic graph

Last Updated : 03 Jun, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a Directed Acyclic Graph (DAG) with V nodes labeled from 0 to V-1, and a list of directed edges, count the total number of distinct paths from a given start node to a destination node. Each edge is represented as edges[i] = [u, v], indicating a directed edge from u to v.

Examples: 

Input: edges[][] = [[0,1], [0,3], [2,0], [2,1], [1,3]], V = 4, src = 2, dest = 3
Output: 3
Explanation: There are three ways to reach at 3 from 2. These are: 2 -> 1 -> 3, 2 -> 0 -> 3 and 2 -> 0 -> 1 -> 3.

Print-all-paths-1

Input: edges[][] = [[0,1], [1,2], [1,3], [2,3]], V = 4, src = 0, dest = 3
Output: 2
Explanation: There is two way to reach at 3 from 0 that is : 0 -> 1 -> 2 -> 3 and 0 -> 1 -> 3.Print-all-paths-2


[Naive Approach] Using Depth First Search - O(2^n) time and O(n) space

The idea is to perform a Depth First Search traversal starting from the source node and count the number of paths reaching destination node.

Step by step approach:

  1. Create an adjacency list from the edges of the graph.
  2. Start DFS from the source node. For each node:
    • If current node is destination node, return 1.
    • Otherwise, for each edge from current node, find the number of paths for the adjacent node recursively and add it to the result.
C++
// C++ program to find Number of paths from source 
// to destination in a directed acyclic graph
#include <bits/stdc++.h>
using namespace std;

int dfs(int u, int dest, vector<vector<int>> &adj) {
    
    // If destination is reached
    if (u == dest) return 1;
    int count = 0;
    
    // Count number of paths from current node 
    // to destination node.
    for (int v : adj[u]) {
        count += dfs(v, dest, adj);
    }
    return count;
}

    int countPaths(vector<vector<int>>& edges, int V, 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 = 4;
    int src = 2, dest = 3;
    vector<vector<int>> edges = 
    {{0,1}, {0,3}, {2,0}, {2,1}, {1,3}};
    cout << countPaths(edges, V, src, dest);
    return 0;
}
Java
// Java program to find Number of paths from source 
// to destination in a directed acyclic graph
import java.util.ArrayList;

class GfG {
    static int dfs(int u, int dest, ArrayList<ArrayList<Integer>> adj) {
        
        // If destination is reached
        if (u == dest) return 1;
        int count = 0;
        
        // Count number of paths from current node 
        // to destination node.
        for (int v : adj.get(u)) {
            count += dfs(v, dest, adj);
        }
        return count;
    }

    static int countPaths( int[][] edges, int V, int src, int dest) {
        ArrayList<ArrayList<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]);
        }
        return dfs(src, dest, adj);
    }

    public static void main(String[] args) {
        int V = 4;
        int src = 2, dest = 3;
        int[][] edges = 
       {{0,1}, {0,3}, {2,0}, {2,1}, {1,3}};
        System.out.println(countPaths(edges, V, src, dest));
    }
}
Python
# Python program to find Number of paths from source 
# to destination in a directed acyclic graph

def dfs(u, dest, adj):
    
    # If destination is reached
    if u == dest:
        return 1
    count = 0
    
    # Count number of paths from current node 
    # to destination node.
    for v in adj[u]:
        count += dfs(v, dest, adj)
    return count

def countPaths( edges, V, src, dest):
    adj = [[] for _ in range(V)]
    for e in edges:
        adj[e[0]].append(e[1])
    return dfs(src, dest, adj)

if __name__ == "__main__":
    V = 4
    src = 2
    dest = 3
    edges = [[0,1], [0,3], [2,0], [2,1], [1,3]]
    print(countPaths(edges, V, src, dest))
C#
// C# program to find Number of paths from source 
// to destination in a directed acyclic graph
using System;
using System.Collections.Generic;

class GfG {
    static int Dfs(int u, int dest, List<List<int>> adj) {
        
        // If destination is reached
        if (u == dest) return 1;
        int count = 0;
        
        // Count number of paths from current node 
        // to destination node.
        foreach (int v in adj[u]) {
            count += Dfs(v, dest, adj);
        }
        return count;
    }

    static int CountPaths(int[,] edges, int V, int src, int dest) {
        List<List<int>> adj = new List<List<int>>();
        for (int i = 0; i < V; i++) {
            adj.Add(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 = 4;
        int src = 2, dest = 3;
        int[,] edges = 
        {{0,1}, {0,3}, {2,0}, {2,1}, {1,3}};
        Console.WriteLine(CountPaths(edges, V, src, dest));
    }
}
JavaScript
// JavaScript program to find Number of paths from source 
// to destination in a directed acyclic graph

function dfs(u, dest, adj) {
    
    // If destination is reached
    if (u === dest) return 1;
    let count = 0;
    
    // Count number of paths from current node 
    // to destination node.
    for (const v of adj[u]) {
        count += dfs(v, dest, adj);
    }
    return count;
}

function countPaths(edges, V, src, dest) {
    const adj = Array.from({ length: V }, () => []);
    for (const e of edges) {
        adj[e[0]].push(e[1]);
    }
    return dfs(src, dest, adj);
}

const V = 4;
const src = 2, dest = 3;
const edges = 
[[0,1], [0,3], [2,0], [2,1], [1,3]];
console.log(countPaths(edges, V, src, dest));

Output
3

[Expected Approach - 1] Using DFS + DP - O(V + E) time and O(V) space

The idea is to avoid re-computation of subproblems by storing the number of paths from each node to the destination in a memoization array.

In the above approach, we can observe that the number of paths from certain nodes is calculated multiple times. In example 1, the number of paths from Node 3 is calculated twice due to edges from 0 and 2. As graph is directed acyclic graph, so the number of paths from each node will remain same for any number of times. So, we can simply compute the result and memoize it.

Below is the recurrence relation:

numberOfPaths(u) = SUM( numberOfPaths(v) ), for each node v such that there exists an edge from u to v.

Base Case:

  • numberOfPaths(u) = 1, if u is equal to destination node.

Step by step approach:

  • Create an adjacency list from the edges.
  • Start Depth First Search from the source node. For each node:
    • Return 1, if the node is the destination node.
    • If the number of paths for this node is already computed, return the memoized value.
    • Otherwise:
      • For each edge from current node, find the number of paths for the adjacent node recursively and add it to the result.
      • Memoize this value and return it.
C++
// C++ program to find Number of paths from source 
// to destination in a directed acyclic graph
#include <bits/stdc++.h>
using namespace std;

int dfs(int u, int dest, vector<vector<int>> &adj, vector<int> &memo) {
    
    // If destination is reached
    if (u == dest) return 1;
    
    // If number of paths from this node 
    // is memoized
    if (memo[u] != -1) return memo[u];
    
    int count = 0;
    for (int v : adj[u]) {
        count += dfs(v, dest, adj, memo);
    }
    
    return memo[u] = count;
}

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

int main() {
    int V = 4;
    int src = 2, dest = 3;
    vector<vector<int>> edges = 
    {{0,1}, {0,3}, {2,0}, {2,1}, {1,3}};
    cout << countPaths(edges, V, src, dest);
    return 0;
}
Java
// Java program to find Number of paths from source 
// to destination in a directed acyclic graph
import java.util.ArrayList;
import java.util.Arrays;

class GfG {
    static int dfs(int u, int dest, 
    ArrayList<ArrayList<Integer>> adj, int[] memo) {
        
        // If destination is reached
        if (u == dest) return 1;
        
        // If number of paths from this node 
        // is memoized
        if (memo[u] != -1) return memo[u];
        
        int count = 0;
        for (int v : adj.get(u)) {
            count += dfs(v, dest, adj, memo);
        }
        
        return memo[u] = count;
    }

    static int countPaths( int[][] edges, int V, int src, int dest) {
        ArrayList<ArrayList<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]);
        }
        int[] memo = new int[V];
        Arrays.fill(memo, -1);
        return dfs(src, dest, adj, memo);
    }

    public static void main(String[] args) {
        int V = 4;
        int src = 2, dest = 3;
        int[][] edges = 
        {{0,1}, {0,3}, {2,0}, {2,1}, {1,3}};
        System.out.println(countPaths(edges, V, src, dest));
    }
}
Python
# Python program to find Number of paths from source 
# to destination in a directed acyclic graph

def dfs(u, dest, adj, memo):
    
    # If destination is reached
    if u == dest:
        return 1
    
    # If number of paths from this node 
    # is memoized
    if memo[u] != -1:
        return memo[u]
    
    count = 0
    for v in adj[u]:
        count += dfs(v, dest, adj, memo)
    
    memo[u] = count
    return count

def countPaths(edges, V, src, dest):
    adj = [[] for _ in range(V)]
    for e in edges:
        adj[e[0]].append(e[1])
    memo = [-1] * V
    return dfs(src, dest, adj, memo)

if __name__ == "__main__":
    V = 4
    src = 2
    dest = 3
    edges = [[0,1], [0,3], [2,0], [2,1], [1,3]]
    print(countPaths(edges, V, src, dest))
C#
// C# program to find Number of paths from source 
// to destination in a directed acyclic graph
using System;
using System.Collections.Generic;

class GfG {
    static int Dfs(int u, int dest, List<List<int>> adj, int[] memo) {
        
        // If destination is reached
        if (u == dest) return 1;
        
        // If number of paths from this node 
        // is memoized
        if (memo[u] != -1) return memo[u];
        
        int count = 0;
        foreach (int v in adj[u]) {
            count += Dfs(v, dest, adj, memo);
        }
        
        return memo[u] = count;
    }

    static int CountPaths(int[,] edges, int V, int src, int dest) {
        List<List<int>> adj = new List<List<int>>();
        for (int i = 0; i < V; i++) {
            adj.Add(new List<int>());
        }
        for (int i = 0; i < edges.GetLength(0); i++) {
            adj[edges[i, 0]].Add(edges[i, 1]);
        }
        int[] memo = new int[V];
        Array.Fill(memo, -1);
        return Dfs(src, dest, adj, memo);
    }

    static void Main() {
        int V = 4;
        int src = 2, dest = 3;
        int[,] edges = 
        {{0,1}, {0,3}, {2,0}, {2,1}, {1,3}};
        Console.WriteLine(CountPaths(edges, V, src, dest));
    }
}
JavaScript
// JavaScript program to find Number of paths from source 
// to destination in a directed acyclic graph

function dfs(u, dest, adj, memo) {
    
    // If destination is reached
    if (u === dest) return 1;
    
    // If number of paths from this node 
    // is memoized
    if (memo[u] !== -1) return memo[u];
    
    let count = 0;
    for (const v of adj[u]) {
        count += dfs(v, dest, adj, memo);
    }
    
    return memo[u] = count;
}

function countPaths( edges, V, src, dest) {
    const adj = Array.from({ length: V }, () => []);
    for (const e of edges) {
        adj[e[0]].push(e[1]);
    }
    const memo = new Array(V).fill(-1);
    return dfs(src, dest, adj, memo);
}

const V = 4;
const src = 2, dest = 3;
const edges = 
[[0,1], [0,3], [2,0], [2,1], [1,3]];
console.log(countPaths(edges, V, src, dest));

Output
3

[Expected Approach - 2] Using DFS + Topological Sort - O(V + E) time and O(V) space

The idea is to process nodes in topological order so that all paths leading to a node are computed before using it to calculate paths for dependent nodes.

In this approach, we are calculating the number of paths for each node from the source node. At the end, we can simply return the number of paths from source to destination by returning the value at destination index.

Step by step approach:

  1. Create an adjacency list and compute in-degree for each node. Also, create an array of size V to store the number of paths for each node from source node.
  2. Set paths[source] = 1, as there is only one path from source to source.
  3. Perform topological sort using Kahn's algorithm. For each node in topological order:
    1. Add its number of paths to all its neighbors.
    2. If in-degree of any neighbor becomes 1, add it to queue.
  4. Return number of paths stored for the destination node.
C++
// C++ program to find Number of paths from source 
// to destination in a directed acyclic graph
#include <bits/stdc++.h>
using namespace std;

int countPaths( vector<vector<int>> &edges, int V, int src, int dest) {
    vector<vector<int>> adj(V);
    vector<int> inDeg(V, 0);
    
    // Create adjancecny list and 
    // find in-degree
    for (auto e: edges) {
        adj[e[0]].push_back(e[1]);
        inDeg[e[1]]++;
    }

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

    vector<int> paths(V, 0);
    paths[src] = 1;

    while (!q.empty()) {
        int u = q.front(); q.pop();
        
        // For each edge u->v, if number of 
        // paths starting from source node to 
        // u'th node is x, then the same paths 
        // will be present for v'th node. 
        for (int v : adj[u]) {
            paths[v] += paths[u];
            if (--inDeg[v] == 0) {
                q.push(v);
            }
        }
    }

    return paths[dest];
}

int main() {
    int V = 4;
    int src = 2, dest = 3;
    vector<vector<int>> edges = 
    {{0,1}, {0,3}, {2,0}, {2,1}, {1,3}};
    cout << countPaths(edges, V, src, dest);
    return 0;
}
Java
// Java program to find Number of paths from source 
// to destination in a directed acyclic graph
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

class GfG {
    static int countPaths(int[][] edges, int V, int src, int dest) {
        ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
        int[] inDeg = new int[V];
        
        // Create adjancecny list and 
        // find in-degree
        for (int i = 0; i < V; i++) {
            adj.add(new ArrayList<>());
        }
        for (int[] e : edges) {
            adj.get(e[0]).add(e[1]);
            inDeg[e[1]]++;
        }

        Queue<Integer> q = new LinkedList<>();
        for (int i = 0; i < V; i++) {
            if (inDeg[i] == 0) q.add(i);
        }

        int[] paths = new int[V];
        paths[src] = 1;

        while (!q.isEmpty()) {
            int u = q.poll();
            
            // For each edge u->v, if number of 
            // paths starting from source node to 
            // u'th node is x, then the same paths 
            // will be present for v'th node.
            for (int v : adj.get(u)) {
                paths[v] += paths[u];
                if (--inDeg[v] == 0) {
                    q.add(v);
                }
            }
        }

        return paths[dest];
    }

    public static void main(String[] args) {
        int V = 4;
        int src = 2, dest = 3;
        int[][] edges = 
        {{0,1}, {0,3}, {2,0}, {2,1}, {1,3}};
        System.out.println(countPaths(edges, V, src, dest));
    }
}
Python
# Python program to find Number of paths from source 
# to destination in a directed acyclic graph
from collections import deque

def countPaths(edges, V, src, dest):
    adj = [[] for _ in range(V)]
    inDeg = [0] * V
    
    # Create adjancecny list and 
    # find in-degree
    for e in edges:
        adj[e[0]].append(e[1])
        inDeg[e[1]] += 1

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

    paths = [0] * V
    paths[src] = 1

    while q:
        u = q.popleft()
        
        # For each edge u->v, if number of 
        # paths starting from source node to 
        # u'th node is x, then the same paths 
        # will be present for v'th node.
        for v in adj[u]:
            paths[v] += paths[u]
            inDeg[v] -= 1
            if inDeg[v] == 0:
                q.append(v)

    return paths[dest]

if __name__ == "__main__":
    V = 4
    src = 2
    dest = 3
    edges = [[0,1], [0,3], [2,0], [2,1], [1,3]]
    print(countPaths(edges, V, src, dest))
C#
// C# program to find Number of paths from source 
// to destination in a directed acyclic graph
using System;
using System.Collections.Generic;

class GfG {
    static int CountPaths(int[,] edges, int V, int src, int dest) {
        List<List<int>> adj = new List<List<int>>();
        int[] inDeg = new int[V];
        
        // Create adjancecny list and 
        // find in-degree
        for (int i = 0; i < V; i++) {
            adj.Add(new List<int>());
        }
        for (int i = 0; i < edges.GetLength(0); i++) {
            adj[edges[i, 0]].Add(edges[i, 1]);
            inDeg[edges[i, 1]]++;
        }

        Queue<int> q = new Queue<int>();
        for (int i = 0; i < V; i++) {
            if (inDeg[i] == 0) q.Enqueue(i);
        }

        int[] paths = new int[V];
        paths[src] = 1;

        while (q.Count > 0) {
            int u = q.Dequeue();
            
            // For each edge u->v, if number of 
            // paths starting from source node to 
            // u'th node is x, then the same paths 
            // will be present for v'th node.
            foreach (int v in adj[u]) {
                paths[v] += paths[u];
                if (--inDeg[v] == 0) {
                    q.Enqueue(v);
                }
            }
        }

        return paths[dest];
    }

    static void Main() {
        int V = 4;
        int src = 2, dest = 3;
        int[,] edges = 
        {{0,1}, {0,3}, {2,0}, {2,1}, {1,3}};
        Console.WriteLine(CountPaths(edges, V, src, dest));
    }
}
JavaScript
// JavaScript program to find Number of paths from source 
// to destination in a directed acyclic graph

function countPaths( edges, V, src, dest) {
    const adj = Array.from({ length: V }, () => []);
    const inDeg = new Array(V).fill(0);
    
    // Create adjancecny list and 
    // find in-degree
    for (const e of edges) {
        adj[e[0]].push(e[1]);
        inDeg[e[1]]++;
    }

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

    const paths = new Array(V).fill(0);
    paths[src] = 1;

    while (q.length > 0) {
        const u = q.shift();
        
        // For each edge u->v, if number of 
        // paths starting from source node to 
        // u'th node is x, then the same paths 
        // will be present for v'th node.
        for (const v of adj[u]) {
            paths[v] += paths[u];
            if (--inDeg[v] === 0) {
                q.push(v);
            }
        }
    }

    return paths[dest];
}

const V = 4;
const src = 2, dest = 3;
const edges = 
[[0,1], [0,3], [2,0], [2,1], [1,3]];
console.log(countPaths(edges, V, src, dest));

Output
3

Next Article

Similar Reads