




from __future__ import annotations

from sys import maxsize
from typing import Generic, TypeVar

UpperCamelCase__    			=			TypeVar("""T""")







def 	_a      (						SCREAMING_SNAKE_CASE_							:				int     ):
					return (position - 1) // 2







def 	_a      (						SCREAMING_SNAKE_CASE_							:				int     ):
					return (2 * position) + 1







def 	_a      (						SCREAMING_SNAKE_CASE_							:				int     ):
					return (2 * position) + 2
class 			a__    (					Generic[T]      ):






						def __init__(   self			):




											"""simple docstring"""



											__lowerCAmelCase				   =       []
											__lowerCAmelCase				   =       {}
											__lowerCAmelCase				   =       0






						def __len__(   self			):




											"""simple docstring"""



											return self.elements






						def __repr__(   self			):




											"""simple docstring"""



											return str(self.heap			)






						def 				__SCREAMING_SNAKE_CASE(   self			):




											"""simple docstring"""



											return self.elements == 0






						def 				__SCREAMING_SNAKE_CASE(   self		,			_A		,			_A			):




											"""simple docstring"""



											self.heap.append((elem, weight)			)
											__lowerCAmelCase				   =       self.elements
											self.elements += 1
											self._bubble_up(_A			)






						def 				__SCREAMING_SNAKE_CASE(   self			):




											"""simple docstring"""



											if self.elements > 1:
																self._swap_nodes(0		,			self.elements - 1			)
											__lowerCAmelCase   ,							__lowerCAmelCase				   =       self.heap.pop()
											del self.position_map[elem]
											self.elements -= 1
											if self.elements > 0:
																__lowerCAmelCase   ,							__lowerCAmelCase				   =       self.heap[0]
																self._bubble_down(_A			)
											return elem






						def 				__SCREAMING_SNAKE_CASE(   self		,			_A		,			_A			):




											"""simple docstring"""



											__lowerCAmelCase				   =       self.position_map[elem]
											__lowerCAmelCase				   =       (elem, weight)
											if position > 0:
																__lowerCAmelCase				   =       get_parent_position(_A			)
																__lowerCAmelCase   ,							__lowerCAmelCase				   =       self.heap[parent_position]
																if parent_weight > weight:
																					self._bubble_up(_A			)
																else:
																					self._bubble_down(_A			)
											else:
																self._bubble_down(_A			)






						def 				__SCREAMING_SNAKE_CASE(   self		,			_A			):




											"""simple docstring"""



											__lowerCAmelCase				   =       self.position_map[elem]
											if curr_pos == 0:
																return None
											__lowerCAmelCase				   =       get_parent_position(_A			)
											__lowerCAmelCase   ,							__lowerCAmelCase				   =       self.heap[curr_pos]
											__lowerCAmelCase   ,							__lowerCAmelCase				   =       self.heap[parent_position]
											if parent_weight > weight:
																self._swap_nodes(_A		,			_A			)
																return self._bubble_up(_A			)
											return None






						def 				__SCREAMING_SNAKE_CASE(   self		,			_A			):




											"""simple docstring"""



											__lowerCAmelCase				   =       self.position_map[elem]
											__lowerCAmelCase   ,							__lowerCAmelCase				   =       self.heap[curr_pos]
											__lowerCAmelCase				   =       get_child_left_position(_A			)
											__lowerCAmelCase				   =       get_child_right_position(_A			)
											if child_left_position < self.elements and child_right_position < self.elements:
																__lowerCAmelCase   ,							__lowerCAmelCase				   =       self.heap[child_left_position]
																__lowerCAmelCase   ,							__lowerCAmelCase				   =       self.heap[child_right_position]
																if child_right_weight < child_left_weight and child_right_weight < weight:
																					self._swap_nodes(_A		,			_A			)
																					return self._bubble_down(_A			)
											if child_left_position < self.elements:
																__lowerCAmelCase   ,							__lowerCAmelCase				   =       self.heap[child_left_position]
																if child_left_weight < weight:
																					self._swap_nodes(_A		,			_A			)
																					return self._bubble_down(_A			)
											else:
																return None
											if child_right_position < self.elements:
																__lowerCAmelCase   ,							__lowerCAmelCase				   =       self.heap[child_right_position]
																if child_right_weight < weight:
																					self._swap_nodes(_A		,			_A			)
																					return self._bubble_down(_A			)
											return None






						def 				__SCREAMING_SNAKE_CASE(   self		,			_A		,			_A			):




											"""simple docstring"""



											__lowerCAmelCase				   =       self.heap[nodea_pos][0]
											__lowerCAmelCase				   =       self.heap[nodea_pos][0]
											__lowerCAmelCase   ,							__lowerCAmelCase				   =       (
											    self.heap[nodea_pos],
											    self.heap[nodea_pos],
											)
											__lowerCAmelCase				   =       nodea_pos
											__lowerCAmelCase				   =       nodea_pos






class 			a__    (					Generic[T]      ):






						def __init__(   self			):




											"""simple docstring"""



											__lowerCAmelCase				   =       {}
											__lowerCAmelCase				   =       0






						def __repr__(   self			):




											"""simple docstring"""



											return str(self.connections			)






						def __len__(   self			):




											"""simple docstring"""



											return self.nodes






						def 				__SCREAMING_SNAKE_CASE(   self		,			_A			):




											"""simple docstring"""



											if node not in self.connections:
																__lowerCAmelCase				   =       {}
																self.nodes += 1






						def 				__SCREAMING_SNAKE_CASE(   self		,			_A		,			_A		,			_A			):




											"""simple docstring"""



											self.add_node(_A			)
											self.add_node(_A			)
											__lowerCAmelCase				   =       weight
											__lowerCAmelCase				   =       weight







def 	_a      (						SCREAMING_SNAKE_CASE_							:				GraphUndirectedWeighted[T]      ,      ):
					__lowerCAmelCase				   =       {node: maxsize for node in graph.connections}
					__lowerCAmelCase				   =       {node: None for node in graph.connections}

					__lowerCAmelCase				   =       MinPriorityQueue()
					for node, weight in dist.items():
										priority_queue.push(SCREAMING_SNAKE_CASE_      ,      SCREAMING_SNAKE_CASE_     )

					if priority_queue.is_empty():
										return dist, parent

					# initialization
					__lowerCAmelCase				   =       priority_queue.extract_min()
					__lowerCAmelCase				   =       0
					for neighbour in graph.connections[node]:
										if dist[neighbour] > dist[node] + graph.connections[node][neighbour]:
															__lowerCAmelCase				   =       dist[node] + graph.connections[node][neighbour]
															priority_queue.update_key(SCREAMING_SNAKE_CASE_      ,      dist[neighbour]     )
															__lowerCAmelCase				   =       node

    # running prim's algorithm
					while not priority_queue.is_empty():
										__lowerCAmelCase				   =       priority_queue.extract_min()
										for neighbour in graph.connections[node]:
															if dist[neighbour] > dist[node] + graph.connections[node][neighbour]:
																				__lowerCAmelCase				   =       dist[node] + graph.connections[node][neighbour]
																				priority_queue.update_key(SCREAMING_SNAKE_CASE_      ,      dist[neighbour]     )
																				__lowerCAmelCase				   =       node
					return dist, parent










from queue import PriorityQueue
from typing import Any

import numpy as np







def 	_a      (						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
										__lowerCAmelCase				   =       cst_fwd.get(SCREAMING_SNAKE_CASE_      ,      np.inf     )
										__lowerCAmelCase				   =       cst_fwd[v] + d
										if new_cost_f < old_cost_f:
															queue.put((new_cost_f, nxt)     )
															__lowerCAmelCase				   =       new_cost_f
															__lowerCAmelCase				   =       v
										if nxt in visited_backward:
															if cst_fwd[v] + d + cst_bwd[nxt] < shortest_distance:
																				__lowerCAmelCase				   =       cst_fwd[v] + d + cst_bwd[nxt]
					return shortest_distance







def 	_a      (						SCREAMING_SNAKE_CASE_							:				str      ,      SCREAMING_SNAKE_CASE_							:				str      ,      SCREAMING_SNAKE_CASE_							:				dict      ,      SCREAMING_SNAKE_CASE_							:				dict     ):
					__lowerCAmelCase				   =       -1

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

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

										__lowerCAmelCase   ,							__lowerCAmelCase				   =       queue_backward.get()
										visited_backward.add(SCREAMING_SNAKE_CASE_     )

										__lowerCAmelCase				   =       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_      ,      )

										__lowerCAmelCase				   =       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:
										__lowerCAmelCase				   =       shortest_distance
					return shortest_path_distance


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




