





class     SCREAMING_SNAKE_CASE__ :



 def __init__(							self ):
        A__											=						{}



 def 				UpperCamelCase			(							self ):
        print(self.vertex )
        for i in self.vertex:
               print(__lowerCamelCase,''' -> ''',''' -> '''.join([str(__lowerCamelCase ) for j in self.vertex[i]] ) )



 def 				UpperCamelCase			(							self,__lowerCamelCase,__lowerCamelCase ):
        # check if vertex is already present,
        if from_vertex in self.vertex:
               self.vertex[from_vertex].append(__lowerCamelCase )
        else:
               # else make a new vertex
               A__											=						[to_vertex]



 def 				UpperCamelCase			(							self ):
        # visited array for storing already visited nodes
        A__											=						[False] * len(self.vertex )

        # call the recursive helper function
        for i in range(len(self.vertex ) ):
               if not visited[i]:
                      self.dfs_recursive(__lowerCamelCase,__lowerCamelCase )




 def 				UpperCamelCase			(							self,__lowerCamelCase,__lowerCamelCase ):
        # mark start vertex as visited
        A__											=						True

        print(__lowerCamelCase,end=''' ''' )

        # Recur for all the vertices that are adjacent to this node
        for i in self.vertex:
               if not visited[i]:
                      self.dfs_recursive(__lowerCamelCase,__lowerCamelCase )


if __name__ == "__main__":
       a__:      Union[str, Any]									=		Graph()
       g.add_edge(0, 1)
       g.add_edge(0, 2)
       g.add_edge(1, 2)
       g.add_edge(2, 0)
       g.add_edge(2, 3)
       g.add_edge(3, 3)

       g.print_graph()
       print('DFS:')
       g.dfs()

       # OUTPUT:
       # 0  ->  1 -> 2
       # 1  ->  2
       # 2  ->  0 -> 3
       # 3  ->  3
       # DFS:
       #  0 1 2 3












a__:      Dict									=		{0: [2, 3], 1: [0], 2: [1], 3: [4], 4: []}

a__:      str									=		{0: [1, 2, 3], 1: [2], 2: [0], 3: [4], 4: [5], 5: [3]}


def 	UpperCamelCase__(       UpperCamelCase__			:       dict[int, list[int]] ,     UpperCamelCase__			:       int ,     UpperCamelCase__			:       list[bool]  )->list[int]:
       A__											=						True
       A__											=						[]

       for neighbour in graph[vert]:
              if not visited[neighbour]:
                     order += topology_sort(UpperCamelCase__ ,     UpperCamelCase__ ,     UpperCamelCase__  )

       order.append(UpperCamelCase__  )

       return order


def 	UpperCamelCase__(       UpperCamelCase__			:       dict[int, list[int]] ,     UpperCamelCase__			:       int ,     UpperCamelCase__			:       list[bool]  )->list[int]:
       A__											=						True
       A__											=						[vert]

       for neighbour in reversed_graph[vert]:
              if not visited[neighbour]:
                     component += find_components(UpperCamelCase__ ,     UpperCamelCase__ ,     UpperCamelCase__  )

       return component


def 	UpperCamelCase__(       UpperCamelCase__			:       dict[int, list[int]]  )->list[list[int]]:
       A__											=						len(UpperCamelCase__  ) * [False]
       A__											=						{vert: [] for vert in range(len(UpperCamelCase__  )  )}

       for vert, neighbours in graph.items():
              for neighbour in neighbours:
                     reversed_graph[neighbour].append(UpperCamelCase__  )

       A__											=						[]
       for i, was_visited in enumerate(UpperCamelCase__  ):
              if not was_visited:
                     order += topology_sort(UpperCamelCase__ ,     UpperCamelCase__ ,     UpperCamelCase__  )

       A__											=						[]
       A__											=						len(UpperCamelCase__  ) * [False]

       for i in range(len(UpperCamelCase__  )  ):
              A__											=						order[len(UpperCamelCase__  ) - i - 1]
              if not visited[vert]:
                     A__											=						find_components(UpperCamelCase__ ,     UpperCamelCase__ ,     UpperCamelCase__  )
                     components_list.append(UpperCamelCase__  )

       return components_list





