

from queue import PriorityQueue
from typing import Any

import numpy as np







def       lowercase					(	__A :					dict ,    __A :					str ,    __A :					set ,    __A :					set ,    __A :					dict ,    __A :					dict ,    __A :					PriorityQueue ,    __A :					dict ,    __A :					float | int ,    )				->			float | int:





    '''simple docstring'''




    for nxt, d in graph[v]:
        if nxt in visited_forward:
            continue
        snake_case							:		Any        =		cst_fwd.get(__A ,    np.inf		)
        snake_case							:		Any        =		cst_fwd[v] + d
        if new_cost_f < old_cost_f:
            queue.put((new_cost_f, nxt)		)
            snake_case							:		Dict        =		new_cost_f
            snake_case							:		int        =		v
        if nxt in visited_backward:
            if cst_fwd[v] + d + cst_bwd[nxt] < shortest_distance:
                snake_case							:		Optional[Any]        =		cst_fwd[v] + d + cst_bwd[nxt]
    return shortest_distance







def       lowercase					(	__A :					str ,    __A :					str ,    __A :					dict ,    __A :					dict		)				->			int:





    '''simple docstring'''




    snake_case							:		Optional[int]        =		-1

    snake_case							:		Union[str, Any]        =		set()
    snake_case							:		Optional[int]        =		set()
    snake_case							:		Union[str, Any]        =		{source: 0}
    snake_case							:		Optional[Any]        =		{destination: 0}
    snake_case							:		Any        =		{source: None}
    snake_case							:		Any        =		{destination: None}
    snake_case							:		PriorityQueue[Any]        =		PriorityQueue()
    snake_case							:		PriorityQueue[Any]        =		PriorityQueue()

    snake_case							:		List[Any]        =		np.inf

    queue_forward.put((0, source)		)
    queue_backward.put((0, destination)		)

    if source == destination:
        return 0

    while not queue_forward.empty() and not queue_backward.empty():
        snake_case      ,		snake_case							:		str        =		queue_forward.get()
        visited_forward.add(__A		)

        snake_case      ,		snake_case							:		str        =		queue_backward.get()
        visited_backward.add(__A		)

        snake_case							:		List[Any]        =		pass_and_relaxation(
            __A ,    __A ,    __A ,    __A ,    __A ,    __A ,    __A ,    __A ,    __A ,    )

        snake_case							:		Any        =		pass_and_relaxation(
            __A ,    __A ,    __A ,    __A ,    __A ,    __A ,    __A ,    __A ,    __A ,    )

        if cst_fwd[v_fwd] + cst_bwd[v_bwd] >= shortest_distance:
            break

    if shortest_distance != np.inf:
        snake_case							:		Any        =		shortest_distance
    return shortest_path_distance


__lowercase     : List[Any]       =						{
    '''B''': [['''C''', 1]],
    '''C''': [['''D''', 1]],
    '''D''': [['''F''', 1]],
    '''E''': [['''B''', 1], ['''G''', 2]],
    '''F''': [],
    '''G''': [['''F''', 1]],
}
__lowercase     : Optional[int]       =						{
    '''B''': [['''E''', 1]],
    '''C''': [['''B''', 1]],
    '''D''': [['''C''', 1]],
    '''F''': [['''D''', 1], ['''G''', 1]],
    '''E''': [[None, np.inf]],
    '''G''': [['''E''', 2]],
}

if __name__ == "__main__":
     import doctest

     doctest.testmod()









class 			lowerCamelCase_				:


 '''simple docstring'''







 def __init__(				self    :						str		):
       SCREAMING_SNAKE_CASE_      		=     {}



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



 def  lowerCAmelCase_    (				self    :						Union[str, Any]							,							_lowerCAmelCase    :						int							,							_lowerCAmelCase    :						int		):
       # check if vertex is already present,
       if from_vertex in self.vertex:
             self.vertex[from_vertex].append(_lowerCAmelCase		)
       else:
             # else make a new vertex
             SCREAMING_SNAKE_CASE_      		=     [to_vertex]



 def  lowerCAmelCase_    (				self    :						Optional[Any]		):
       # visited array for storing already visited nodes
       SCREAMING_SNAKE_CASE_      		=     [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  lowerCAmelCase_    (				self    :						Tuple							,							_lowerCAmelCase    :						int							,							_lowerCAmelCase    :						list		):
       # mark start vertex as visited
       SCREAMING_SNAKE_CASE_      		=     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__":
   lowerCamelCase__					:  List[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