All paths in a directed acyclic graph

Finding all the paths in a directed acyclic graph from a source node to a destination node

All paths in a directed acyclic graph can be found using Depth-First-Search traversal. Idea is to start from the source node and use DFS to reach the destination while storing the nodes along the path. Once the destination node is found, the path is stored. The DFS traversal does not mark the nodes as visited while searching for the destination as a node in between can be revisited if it is present in a different path.


Algorithm Find_All_Paths (Graph g)
1.  Push the source node ‘src’ in the path.
2.  DFS (src, dest, g)

DFS (Source src, Destination dest, Graph g)
1.  If (src == dest) then
2.      A path has been found. Push the path in the list of all_the_paths.
3.  Else
4.     For every adjacent node ‘adj_node’ that is adjacent to src do
5.        Push ‘adj_node’ in the path.
6.        DFS (adj_node, dest, g)
7.        Pop ‘adj_node’ from the path. This is essentially a backtracing mechanism to find a different path from the source (‘src’) node.


Consider the below graph. The DFS traversal starts from the source 0 before the destination 3 is found. During the traversal, nodes 1 and 2 are visited before the desitnation 3 is reached. Since no nodes are marked visited, a different path is found that may pass through nodes 1 or 2 before reaching the desination 3.
Thus the DFS finds out the below paths..
[ 0 -> 1 -> 2 -> 3 ], path found.
Popout node 3 & 2. Next node ‘3’ adjacent to node 1 is visited.
[ 0 -> 1 -> 3 ], path found.
Popout node 3 & 1. Next node ‘2’ adjacent to node 0 is visited.
[ 0 -> 2 -> 3 ], path found.

Example of all the paths present in a directed acyclic graph

All_Paths_In_A_Graph


Java

Java Program for finding all paths in a directed acyclic graph using DFS.


C++ Program for finding all the paths in a directed acyclic graph using DFS

#include<iostream>
#include<vector>
using namespace std;

class Graph {

private :
    vector<int> path;
    vector<vector<int>> allpaths;
    int dest;
    int src;

public:
    vector<vector<int>> FindAllPaths(vector<vector<int>>& graph) {
        // Clear previously stored paths
        path.clear();
        allpaths.clear();

        dest = graph.size()-1;
        path.push_back(src);
        cout << "Source : " << src << " Destination : " << dest << endl;
        DFS(src, graph);
        return allpaths;
    }

    void DFS(int src, vector<vector<int>>& graph) {

        if (src == dest) {
            allpaths.push_back(path);
        } else {
            for (const auto& adjnode : graph[src]) {
                path.push_back(adjnode);
                DFS(adjnode, graph);
                path.pop_back();
            }
        }
    }   
};

void PrintAllPaths(vector<vector<int>> allpaths) {
    for (const auto& path : allpaths) {
        for (const auto& node : path)
            cout << node << " ";
        cout << endl;
    }
    cout << endl;
    allpaths.clear();
}

int main() {

    vector<vector<int>> g1 = {{1,2}, {3}, {3}, {}}; // 0 -> (1,2); 1 -> (3); 2 -> (3); 3 -> (None)
    /*  2 ---> 3
        ^      ^   
        |      |        
        0 ---> 1
    */
    vector<vector<int>> g2 = {{1,2}, {2,3}, {3}, {}}; // 0 -> (1,2); 1 -> (2,3); 2 -> (3); 3 -> (None)
    vector<vector<int>> g3 = {{4,3,1}, {3,2,4}, {3}, {4}, {}};

    Graph g;
    vector<vector<int>> allpaths;

    cout << "All paths in graph G1" << endl;
    allpaths = g.FindAllPaths(g1);
    PrintAllPaths(allpaths);
   
    cout << "All paths in graph G2" << endl;
    allpaths = g.FindAllPaths(g2);
    PrintAllPaths(allpaths);

    cout << "All paths in graph G3" << endl;
    allpaths = g.FindAllPaths(g3);
    PrintAllPaths(allpaths);

    return 0;
}

Output

All paths in graph G1
Source : 0 Destination : 3
0 1 3 
0 2 3 

All paths in graph G2
Source : 0 Destination : 3
0 1 2 3 
0 1 3 
0 2 3 

All paths in graph G3
Source : 0 Destination : 4
0 4 
0 3 4 
0 1 3 4 
0 1 2 3 4 
0 1 4 

Copyright (c) 2020-2021, Algotree.org.
All rights reserved.