<p>Given a directed acyclic graph (<strong>DAG</strong>) of <code>n</code> nodes labeled from <code>0</code> to <code>n - 1</code>, find all possible paths from node <code>0</code> to node <code>n - 1</code> and return them in <strong>any order</strong>.</p>

<p>The graph is given as follows: <code>graph[i]</code> is a list of all nodes you can visit from node <code>i</code> (i.e., there is a directed edge from node <code>i</code> to node <code>graph[i][j]</code>).</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/09/28/all_1.jpg" style="width: 242px; height: 242px;" />
<pre>
<strong>Input:</strong> graph = [[1,2],[3],[3],[]]
<strong>Output:</strong> [[0,1,3],[0,2,3]]
<strong>Explanation:</strong> There are two paths: 0 -&gt; 1 -&gt; 3 and 0 -&gt; 2 -&gt; 3.
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/09/28/all_2.jpg" style="width: 423px; height: 301px;" />
<pre>
<strong>Input:</strong> graph = [[4,3,1],[3,2,4],[3],[4],[]]
<strong>Output:</strong> [[0,4],[0,3,4],[0,1,3,4],[0,1,2,3,4],[0,1,4]]
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>n == graph.length</code></li>
	<li><code>2 &lt;= n &lt;= 15</code></li>
	<li><code>0 &lt;= graph[i][j] &lt; n</code></li>
	<li><code>graph[i][j] != i</code> (i.e., there will be no self-loops).</li>
	<li>All the elements of <code>graph[i]</code> are <strong>unique</strong>.</li>
	<li>The input graph is <strong>guaranteed</strong> to be a <strong>DAG</strong>.</li>
</ul>

class Solution {
private:
    vector<vector<int>> all_paths;
    int destination;

public:
    void dfs_recursive(int cur_node, vector<int>& path, vector<bool>& visited,
             vector<vector<int>>& graph) {
        if (visited[cur_node]) {
            return;
        }

        visited[cur_node] = true;
        path.push_back(cur_node);

        if (cur_node == destination) {
            all_paths.push_back(path);
        }

        // Explore unvisited neighbors
        for (auto& neighbor : graph[cur_node]) {
            if (!visited[neighbor]) {
                dfs_recursive(neighbor, path, visited, graph);
            }
        }

        // Back-tracking after exploring all neighbors
        // Mark as unvisited
        visited[cur_node] = false;

        // If path is a reference, pop_back the path..
        path.pop_back();
    }

    void dfs_iterative(int src, vector<vector<int>>& graph) {
        // Stack stores a pair of node and the path till that node
        stack<pair<int, vector<int>>> dfs_stack;

        // Push src
        dfs_stack.push(make_pair(src, vector<int>{src}));

        vector<bool> visited(graph.size(), false);

        while (!dfs_stack.empty()) {
            pair<int, vector<int>> node_entry = dfs_stack.top();
            dfs_stack.pop();

            int node = node_entry.first;
            vector<int> path = node_entry.second;

            if (visited[node]) {
                continue;
            }

            visited[node] = true;
            
            for (auto& neighbor : graph[node]) {
                // Create a new path for each neighbor
                vector<int> new_path(path);
                new_path.push_back(neighbor);

                if (neighbor == destination) {
                    all_paths.push_back(new_path);
                }

                dfs_stack.push(make_pair(neighbor, new_path));
            }

            visited[node] = false;
        }
    }

    vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
        int n = graph.size();
        destination = n - 1;

        vector<bool> visited(n, false);
        vector<int> path;

        // dfs_recursive(0, path, visited, graph);
        dfs_iterative(0, graph);

        return all_paths;
    }
};
25636