<p>There is a <strong>directed</strong> graph consisting of <code>n</code> nodes numbered from <code>0</code> to <code>n - 1</code> and <code>n</code> directed edges.</p>

<p>You are given a <strong>0-indexed</strong> array <code>edges</code> where <code>edges[i]</code> indicates that there is an edge from node <code>i</code> to node <code>edges[i]</code>.</p>

<p>Consider the following process on the graph:</p>

<ul>
	<li>You start from a node <code>x</code> and keep visiting other nodes through edges until you reach a node that you have already visited before on this <strong>same</strong> process.</li>
</ul>

<p>Return <em>an array </em><code>answer</code><em> where </em><code>answer[i]</code><em> is the number of <strong>different</strong> nodes that you will visit if you perform the process starting from node </em><code>i</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2023/08/31/graaphdrawio-1.png" />
<pre>
<strong>Input:</strong> edges = [1,2,0,0]
<strong>Output:</strong> [3,3,3,4]
<strong>Explanation:</strong> We perform the process starting from each node in the following way:
- Starting from node 0, we visit the nodes 0 -&gt; 1 -&gt; 2 -&gt; 0. The number of different nodes we visit is 3.
- Starting from node 1, we visit the nodes 1 -&gt; 2 -&gt; 0 -&gt; 1. The number of different nodes we visit is 3.
- Starting from node 2, we visit the nodes 2 -&gt; 0 -&gt; 1 -&gt; 2. The number of different nodes we visit is 3.
- Starting from node 3, we visit the nodes 3 -&gt; 0 -&gt; 1 -&gt; 2 -&gt; 0. The number of different nodes we visit is 4.
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2023/08/31/graaph2drawio.png" style="width: 191px; height: 251px;" />
<pre>
<strong>Input:</strong> edges = [1,2,3,4,0]
<strong>Output:</strong> [5,5,5,5,5]
<strong>Explanation:</strong> Starting from any node we can visit every node in the graph in the process.
</pre>

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

<ul>
	<li><code>n == edges.length</code></li>
	<li><code>2 &lt;= n &lt;= 10<sup>5</sup></code></li>
	<li><code>0 &lt;= edges[i] &lt;= n - 1</code></li>
	<li><code>edges[i] != i</code></li>
</ul>

class Solution:
    # def countVisitedNodes(self, edges: List[int]) -> List[int]:
    #     class Solution:

    def depth_first_search(self , cycle_detected_node , current_node , adjacency_list , visited_set , count_of_visited_nodes_for_each_node_list):
        
        if(current_node in visited_set):

            # If the "current_node" is already present in the "visited_set" means this is the "Node" that causes "The Cycle"

            # So , the "cycle_detected_node" is updated as "current_node"
            
            cycle_detected_node[0] = current_node

            # Return the "Count" of "current_node" in "count_of_visited_nodes_for_each_node_list"
            
            return count_of_visited_nodes_for_each_node_list[current_node]
        
        # Add the "current_node" to the "visited_set"

        visited_set.add(current_node)

        # Now , the count is nothing but "(1 + DFS())"

        # The DFS is called now with the "current_node" as the "adjacency_list[current_node]"
        
        count_of_visited_nodes_for_each_node_list[current_node] = (1 + self.depth_first_search(cycle_detected_node , adjacency_list[current_node] , adjacency_list , visited_set , count_of_visited_nodes_for_each_node_list))

        # The Game Changing Logic is Here !

        # If the "current_node" is also the "cycle_detected_node" means , All the other "Nodes" in the "Cycle Detected Path's" count is updated as same

        if(cycle_detected_node[0] == current_node):

            # The loop starts and iterates with the help of the "neighbour_node" which is initialized with the "current_node" and all the other "Nodes" in the "Path" is also updates as the same count

            neighbour_node = adjacency_list[current_node]

            # The while() loop runs for the "Path" starting from "current_node"

            while(neighbour_node != current_node):
                
                # The count of all the "neighbour_node" in the "Path" is updated as the "Count" of "Visited Node" of "current_node"

                count_of_visited_nodes_for_each_node_list[neighbour_node] = count_of_visited_nodes_for_each_node_list[current_node]

                # Now , the "neighbour_node" is updated as the "adjacency_list[neighbour_node]" which will be the next node in the "Path"

                neighbour_node = adjacency_list[neighbour_node]
            
            # Now , Just "re-initialize" the "cycle_detected_count" to a dummy_value , here i took the dummy value as -999
            
            cycle_detected_node[0] = -999
        
        # Finally , return the "count_of_visited_nodes_for_each_node_list[current_node]"

        return count_of_visited_nodes_for_each_node_list[current_node]

    def countVisitedNodes(self , edges_list : List[int]) -> List[int]:

        # The Number of Nodes is the length of "edges_list"

        N = len(edges_list)

        # "visited_set" to keep track of the nodes which has already been visited

        visited_set = set()

        # Initialize the "count_of_visited_nodes_for_each_node_list" to 0 for the length of "N"

        count_of_visited_nodes_for_each_node_list = [0 for i in range(0 , N)]

        # Iterate through all the "Node" which has not yet "Visited"

        for index in range(0 , N):

            # The Condition to avoid DFS calling for the Nodes again and again which has already been "Visited"

            if(index not in visited_set):

                # Intialize the "cycle_detected_node" to a dummy_value here I took -999 as my dummy_value

                # Since we need it to be updated and reflected in the actual varible we need to use "Pass-By Reference" which i have achieved with the help of "List"

                cycle_detected_node = [-999]

                # Now , the DFS call is made

                self.depth_first_search(cycle_detected_node , index , edges_list , visited_set , count_of_visited_nodes_for_each_node_list)
        
        # Atlast , Return the "count_of_visited_nodes_for_each_node_list" which will have the count of all visited nodes for each node
        
        return count_of_visited_nodes_for_each_node_list
1235