



def 		UpperCamelCase	(   snake_case__       :    dict	)	->     bool:
   UpperCamelCase    :  set[int]							=	set()
   # To detect a back edge, keep track of vertices currently in the recursion stack
   UpperCamelCase    :  set[int]							=	set()
   return any(
       node not in visited and depth_first_search(snake_case__       ,     snake_case__       ,     snake_case__       ,     snake_case__	)
       for node in graph	)
def 		UpperCamelCase	(   snake_case__       :    dict       ,     snake_case__       :    int       ,     snake_case__       :    set       ,     snake_case__       :    set	)	->     bool:
   visited.add(snake_case__	)
   rec_stk.add(snake_case__	)

   for node in graph[vertex]:
      if node not in visited:
         if depth_first_search(snake_case__       ,     snake_case__       ,     snake_case__       ,     snake_case__	):
            return True
      elif node in rec_stk:
         return True

    # The node needs to be removed from recursion stack before function ends
   rec_stk.remove(snake_case__	)
   return False


if __name__ == "__main__":
    from doctest import testmod

    testmod()








from __future__ import annotations

__UpperCAmelCase          =       {
    '''A''': ['''B''', '''C''', '''E'''],
    '''B''': ['''A''', '''D''', '''E'''],
    '''C''': ['''A''', '''F''', '''G'''],
    '''D''': ['''B'''],
    '''E''': ['''A''', '''B''', '''D'''],
    '''F''': ['''C'''],
    '''G''': ['''C'''],
}



class 				lowerCAmelCase_		:
       def __init__(			self,			SCREAMING_SNAKE_CASE_,			SCREAMING_SNAKE_CASE_       )     ->		None:
          UpperCamelCase    :  Union[str, Any]							=	graph
          # mapping node to its parent in resulting breadth first tree
          UpperCamelCase    :  dict[str, str | None]							=	{}
          UpperCamelCase    :  Union[str, Any]							=	source_vertex
       def 					snake_case_       (			self       )     ->		None:
          UpperCamelCase    :  str							=	{self.source_vertex}
          UpperCamelCase    :  str							=	None
          UpperCamelCase    :  int							=	[self.source_vertex]  # first in first out queue

          while queue:
             UpperCamelCase    :  Dict							=	queue.pop(0       )
             for adjacent_vertex in self.graph[vertex]:
                if adjacent_vertex not in visited:
                   visited.add(SCREAMING_SNAKE_CASE_       )
                   UpperCamelCase    :  Tuple							=	vertex
                   queue.append(SCREAMING_SNAKE_CASE_       )






       def 					snake_case_       (			self,			SCREAMING_SNAKE_CASE_       )     ->		str:
          if target_vertex == self.source_vertex:
             return self.source_vertex

          UpperCamelCase    :  Optional[Any]							=	self.parent.get(SCREAMING_SNAKE_CASE_       )
          if target_vertex_parent is None:
             UpperCamelCase    :  Union[str, Any]							=	(
                 F"""No path from vertex: {self.source_vertex} to vertex: {target_vertex}"""
             )
             raise ValueError(SCREAMING_SNAKE_CASE_       )

          return self.shortest_path(SCREAMING_SNAKE_CASE_       ) + F"""->{target_vertex}"""


if __name__ == "__main__":
    __UpperCAmelCase          =       Graph(graph, '''G''')
    g.breath_first_search()
    print(g.shortest_path('''D'''))
    print(g.shortest_path('''G'''))
    print(g.shortest_path('''Foo'''))



