


from queue import PriorityQueue
from typing import Any

import numpy as np

def 						_UpperCAmelCase				(			SCREAMING_SNAKE_CASE__			:					dict			,     SCREAMING_SNAKE_CASE__			:					str			,     SCREAMING_SNAKE_CASE__			:					set			,     SCREAMING_SNAKE_CASE__			:					set			,     SCREAMING_SNAKE_CASE__			:					dict			,     SCREAMING_SNAKE_CASE__			:					dict			,     SCREAMING_SNAKE_CASE__			:					PriorityQueue			,     SCREAMING_SNAKE_CASE__			:					dict			,     SCREAMING_SNAKE_CASE__			:					float | int			,     ):
     for nxt, d in graph[v]:
          if nxt in visited_forward:
               continue
          __UpperCamelCase    							=cst_fwd.get(SCREAMING_SNAKE_CASE__			,     np.inf				)
          __UpperCamelCase    							=cst_fwd[v] + d
          if new_cost_f < old_cost_f:
               queue.put((new_cost_f, nxt)				)
               __UpperCamelCase    							=new_cost_f
               __UpperCamelCase    							=v
          if nxt in visited_backward:
               if cst_fwd[v] + d + cst_bwd[nxt] < shortest_distance:
                    __UpperCamelCase    							=cst_fwd[v] + d + cst_bwd[nxt]
     return shortest_distance

def 						_UpperCAmelCase				(			SCREAMING_SNAKE_CASE__			:					str			,     SCREAMING_SNAKE_CASE__			:					str			,     SCREAMING_SNAKE_CASE__			:					dict			,     SCREAMING_SNAKE_CASE__			:					dict				):
     __UpperCamelCase    							=-1

     __UpperCamelCase    							=set()
     __UpperCamelCase    							=set()
     __UpperCamelCase    							={source: 0}
     __UpperCamelCase    							={destination: 0}
     __UpperCamelCase    							={source: None}
     __UpperCamelCase    							={destination: None}
     __UpperCamelCase    							=PriorityQueue()
     __UpperCamelCase    							=PriorityQueue()

     __UpperCamelCase    							=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():
          __UpperCamelCase							,      __UpperCamelCase    							=queue_forward.get()
          visited_forward.add(SCREAMING_SNAKE_CASE__				)

          __UpperCamelCase							,      __UpperCamelCase    							=queue_backward.get()
          visited_backward.add(SCREAMING_SNAKE_CASE__				)

          __UpperCamelCase    							=pass_and_relaxation(
              SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     )

          __UpperCamelCase    							=pass_and_relaxation(
              SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     SCREAMING_SNAKE_CASE__			,     )

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

     if shortest_distance != np.inf:
          __UpperCamelCase    							=shortest_distance
     return shortest_path_distance


_A		       =						{
    'B': [['C', 1]],
    'C': [['D', 1]],
    'D': [['F', 1]],
    'E': [['B', 1], ['G', 2]],
    'F': [],
    'G': [['F', 1]],
}
_A		       =						{
    '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()









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

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

def 						_UpperCAmelCase				(			SCREAMING_SNAKE_CASE__			:					dict[int, list[int]]			,     SCREAMING_SNAKE_CASE__			:					int			,     SCREAMING_SNAKE_CASE__			:					list[bool]				):
     __UpperCamelCase    							=True
     __UpperCamelCase    							=[]

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

     order.append(SCREAMING_SNAKE_CASE__				)

     return order

def 						_UpperCAmelCase				(			SCREAMING_SNAKE_CASE__			:					dict[int, list[int]]			,     SCREAMING_SNAKE_CASE__			:					int			,     SCREAMING_SNAKE_CASE__			:					list[bool]				):
     __UpperCamelCase    							=True
     __UpperCamelCase    							=[vert]

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

     return component





def 						_UpperCAmelCase				(			SCREAMING_SNAKE_CASE__			:					dict[int, list[int]]				):
     __UpperCamelCase    							=len(SCREAMING_SNAKE_CASE__				) * [False]
     __UpperCamelCase    							={vert: [] for vert in range(len(SCREAMING_SNAKE_CASE__				)				)}

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

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

     __UpperCamelCase    							=[]
     __UpperCamelCase    							=len(SCREAMING_SNAKE_CASE__				) * [False]

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

     return components_list





