




"""simple docstring"""



import math
import sys




class       UpperCAmelCase_    :




    def __init__(       self		:			Optional[int] ) ->				str:




     '''simple docstring'''

     A__			=							0
     A__			=							[]
     A__			=							{}  # To store the pos of node in array




    def 				__magic_name__				(       self		:			List[str] ) ->				Dict:




     '''simple docstring'''

     return self.cur_size == 0




    def 				__magic_name__				(       self		:			Optional[Any]      ,					snake_case_		:			Optional[Any] ) ->				Optional[Any]:




     '''simple docstring'''

     A__			=							self.left(__lowercase )
     A__			=							self.right(__lowercase )
     if lc < self.cur_size and self.array(__lowercase )[0] < self.array(__lowercase )[0]:
      A__			=							lc
     else:
      A__			=							idx
     if rc < self.cur_size and self.array(__lowercase )[0] < self.array(__lowercase )[0]:
      A__			=							rc
     if smallest != idx:
      self.swap(__lowercase      ,					__lowercase )
      self.min_heapify(__lowercase )




    def 				__magic_name__				(       self		:			List[str]      ,					snake_case_		:			Optional[int] ) ->				Optional[Any]:




     '''simple docstring'''

     A__			=							self.cur_size
     self.cur_size += 1
     self.array.append((sys.maxsize, tup[1]) )
     self.decrease_key((sys.maxsize, tup[1])      ,					tup[0] )




    def 				__magic_name__				(       self		:			List[Any] ) ->				List[Any]:




     '''simple docstring'''

     A__			=							self.array[0][1]
     A__			=							self.array[self.cur_size - 1]
     self.cur_size -= 1
     self.min_heapify(1 )
     del self.pos[min_node]
     return min_node




    def 				__magic_name__				(       self		:			Union[str, Any]      ,					snake_case_		:			Optional[int] ) ->				Optional[int]:




     '''simple docstring'''

     return 2 * i + 1




    def 				__magic_name__				(       self		:			Optional[Any]      ,					snake_case_		:			List[Any] ) ->				Tuple:




     '''simple docstring'''

     return 2 * i + 2




    def 				__magic_name__				(       self		:			Optional[int]      ,					snake_case_		:			List[Any] ) ->				Optional[Any]:




     '''simple docstring'''

     return math.floor(i / 2 )




    def 				__magic_name__				(       self		:			Tuple      ,					snake_case_		:			int      ,					snake_case_		:			Union[str, Any] ) ->				Dict:




     '''simple docstring'''

     A__			=							j
     A__			=							i
     A__			=							self.array[i]
     A__			=							self.array[j]
     A__			=							temp




    def 				__magic_name__				(       self		:			Optional[Any]      ,					snake_case_		:			Optional[int]      ,					snake_case_		:			Optional[Any] ) ->				int:




     '''simple docstring'''

     A__			=							self.pos[tup[1]]
     # assuming the new_d is atmost old_d
     A__			=							(new_d, tup[1])
     while idx > 0 and self.array[self.par(__lowercase )][0] > self.array[idx][0]:
      self.swap(__lowercase      ,					self.par(__lowercase ) )
      A__			=							self.par(__lowercase )






class       UpperCAmelCase_    :




    def __init__(       self		:			Optional[Any]      ,					snake_case_		:			int ) ->				Optional[Any]:




     '''simple docstring'''

     A__			=							{}  # To store graph: u -> (v,w)
     A__			=							num  # Number of nodes in graph
     # To store the distance from source vertex
     A__			=							[0] * self.num_nodes
     A__			=							[-1] * self.num_nodes  # To store the path




    def 				__magic_name__				(       self		:			int      ,					snake_case_		:			List[Any]      ,					snake_case_		:			List[Any]      ,					snake_case_		:			Optional[int] ) ->				Tuple:




     '''simple docstring'''

     if u in self.adjList:
      self.adjList[u].append((v, w) )
     else:
      A__			=							[(v, w)]

     # Assuming undirected graph
     if v in self.adjList:
      self.adjList[v].append((u, w) )
     else:
      A__			=							[(u, w)]




    def 				__magic_name__				(       self		:			Dict ) ->				int:




     '''simple docstring'''

     for u in self.adjList:
      print(__lowercase      ,					"->"      ,					" -> ".join(str(F"""{v}({w})""" ) for v, w in self.adjList[u] ) )




    def 				__magic_name__				(       self		:			Any      ,					snake_case_		:			int ) ->				Optional[int]:




     '''simple docstring'''

     A__			=							[-1] * self.num_nodes
     # src is the source node
     A__			=							0
     A__			=							PriorityQueue()
     q.insert((0, src) )  # (dist from src, node)
     for u in self.adjList:
      if u != src:
       A__			=							sys.maxsize  # Infinity
       A__			=							-1

     while not q.is_empty():
      A__			=							q.extract_min()  # Returns node with the min dist from source
      # Update the distance of all the neighbours of u and
      # if their prev dist was INFINITY then push them in Q
      for v, w in self.adjList[u]:
       A__			=							self.dist[u] + w
       if self.dist[v] > new_dist:
        if self.dist[v] == sys.maxsize:
         q.insert((new_dist, v) )
        else:
         q.decrease_key((self.dist[v], v)      ,					__lowercase )
        A__			=							new_dist
        A__			=							u

        # Show the shortest distances from src
     self.show_distances(__lowercase )




    def 				__magic_name__				(       self		:			List[str]      ,					snake_case_		:			Optional[int] ) ->				Optional[int]:




     '''simple docstring'''

     print(F"""Distance from node: {src}""" )
     for u in range(self.num_nodes ):
      print(F"""Node {u} has distance: {self.dist[u]}""" )




    def 				__magic_name__				(       self		:			str      ,					snake_case_		:			int      ,					snake_case_		:			str ) ->				List[str]:




     '''simple docstring'''

     A__			=							[]
     A__			=							0
     A__			=							dest
     # Backtracking from dest to src
     while self.par[temp] != -1:
      path.append(__lowercase )
      if temp != src:
       for v, w in self.adjList[temp]:
        if v == self.par[temp]:
         cost += w
         break
      A__			=							self.par[temp]
     path.append(__lowercase )
     path.reverse()

     print(F"""----Path to reach {dest} from {src}----""" )
     for u in path:
      print(F"""{u}"""      ,					end=" " )
      if u != dest:
       print("-> "      ,					end="" )

     print("\nTotal cost of path: "      ,					__lowercase )


if __name__ == "__main__":
      SCREAMING_SNAKE_CASE							=			Graph(9)
      graph.add_edge(0, 1, 4)
      graph.add_edge(0, 7, 8)
      graph.add_edge(1, 2, 8)
      graph.add_edge(1, 7, 11)
      graph.add_edge(2, 3, 7)
      graph.add_edge(2, 8, 2)
      graph.add_edge(2, 5, 4)
      graph.add_edge(3, 4, 9)
      graph.add_edge(3, 5, 14)
      graph.add_edge(4, 5, 10)
      graph.add_edge(5, 6, 2)
      graph.add_edge(6, 7, 1)
      graph.add_edge(6, 8, 6)
      graph.add_edge(7, 8, 7)
      graph.show_graph()
      graph.dijkstra(0)
      graph.show_path(0, 4)

# OUTPUT
# 0 -> 1(4) -> 7(8)
# 1 -> 0(4) -> 2(8) -> 7(11)
# 7 -> 0(8) -> 1(11) -> 6(1) -> 8(7)
# 2 -> 1(8) -> 3(7) -> 8(2) -> 5(4)
# 3 -> 2(7) -> 4(9) -> 5(14)
# 8 -> 2(2) -> 6(6) -> 7(7)
# 5 -> 2(4) -> 3(14) -> 4(10) -> 6(2)
# 4 -> 3(9) -> 5(10)
# 6 -> 5(2) -> 7(1) -> 8(6)
# Distance from node: 0
# Node 0 has distance: 0
# Node 1 has distance: 4
# Node 2 has distance: 12
# Node 3 has distance: 19
# Node 4 has distance: 21
# Node 5 has distance: 11
# Node 6 has distance: 9
# Node 7 has distance: 8
# Node 8 has distance: 14
# ----Path to reach 4 from 0----
# 0 -> 7 -> 6 -> 5 -> 4
# Total cost of path:  21












def        A__						(							SCREAMING_SNAKE_CASE_				,							SCREAMING_SNAKE_CASE_		) ->  Union[str, Any]:
		if n < 0:
				return 0
		# table[i] represents the number of ways to get to amount i
		lowerCamelCase :			int    		=[0] * (n + 1)

		# There is exactly 1 way to get to zero(You pick no coins).
		lowerCamelCase :			List[Any]    		=1

		# Pick all coins one by one and update table[] values
		# after the index greater than or equal to the value of the
		# picked coin
		for coin_val in s:
				for j in range(SCREAMING_SNAKE_CASE_				,							n + 1		):
						table[j] += table[j - coin_val]

		return table[n]


if __name__ == "__main__":
				import doctest

				doctest.testmod()

