






import math
import sys
class 					a					:



      """simple docstring"""


      def __init__(   self      :    Any      )							->   Dict:
        __UpperCAmelCase							:			Dict     =						0
        __UpperCAmelCase							:			Optional[Any]     =						[]
        __UpperCAmelCase							:			List[Any]     =						{}  # To store the pos of node in array
      def 			UpperCAmelCase   (   self      :    int      )							->   Optional[int]:
        return self.cur_size == 0
      def 			UpperCAmelCase   (   self      :    Dict	,   __lowercase      :    Optional[int]      )							->   List[str]:
        __UpperCAmelCase							:			Tuple     =						self.left(__lowercase      )
        __UpperCAmelCase							:			int     =						self.right(__lowercase      )
        if lc < self.cur_size and self.array(__lowercase      )[0] < self.array(__lowercase      )[0]:
          __UpperCAmelCase							:			str     =						lc
        else:
          __UpperCAmelCase							:			str     =						idx
        if rc < self.cur_size and self.array(__lowercase      )[0] < self.array(__lowercase      )[0]:
          __UpperCAmelCase							:			int     =						rc
        if smallest != idx:
          self.swap(__lowercase	,   __lowercase      )
          self.min_heapify(__lowercase      )
      def 			UpperCAmelCase   (   self      :    int	,   __lowercase      :    Any      )							->   Union[str, Any]:
        # Inserts a node into the Priority Queue
        __UpperCAmelCase							:			Optional[int]     =						self.cur_size
        self.cur_size += 1
        self.array.append((sys.maxsize, tup[1])      )
        self.decrease_key((sys.maxsize, tup[1])	,   tup[0]      )
      def 			UpperCAmelCase   (   self      :    Optional[Any]      )							->   Optional[int]:
        # Removes and returns the min element at top of priority queue
        __UpperCAmelCase							:			List[str]     =						self.array[0][1]
        __UpperCAmelCase							:			Optional[int]     =						self.array[self.cur_size - 1]
        self.cur_size -= 1
        self.min_heapify(1      )
        del self.pos[min_node]
        return min_node
      def 			UpperCAmelCase   (   self      :    Any	,   __lowercase      :    Any      )							->   Union[str, Any]:
        # returns the index of left child
        return 2 * i + 1
      def 			UpperCAmelCase   (   self      :    Union[str, Any]	,   __lowercase      :    Optional[Any]      )							->   List[str]:
        # returns the index of right child
        return 2 * i + 2
      def 			UpperCAmelCase   (   self      :    Optional[Any]	,   __lowercase      :    List[str]      )							->   Optional[int]:
        # returns the index of parent
        return math.floor(i / 2      )
      def 			UpperCAmelCase   (   self      :    Union[str, Any]	,   __lowercase      :    Dict	,   __lowercase      :    str      )							->   Dict:
        # swaps array elements at indices i and j
        # update the pos{}
        __UpperCAmelCase							:			Any     =						j
        __UpperCAmelCase							:			Dict     =						i
        __UpperCAmelCase							:			Optional[int]     =						self.array[i]
        __UpperCAmelCase							:			Optional[Any]     =						self.array[j]
        __UpperCAmelCase							:			Any     =						temp




      def 			UpperCAmelCase   (   self      :    Optional[Any]	,   __lowercase      :    Dict	,   __lowercase      :    Dict      )							->   Union[str, Any]:
        __UpperCAmelCase							:			Optional[Any]     =						self.pos[tup[1]]
        # assuming the new_d is atmost old_d
        __UpperCAmelCase							:			Dict     =						(new_d, tup[1])
        while idx > 0 and self.array[self.par(__lowercase      )][0] > self.array[idx][0]:
          self.swap(__lowercase	,   self.par(__lowercase      )      )
          __UpperCAmelCase							:			Optional[Any]     =						self.par(__lowercase      )


class 					a					:



      """simple docstring"""


      def __init__(   self      :    List[Any]	,   __lowercase      :    int      )							->   Union[str, Any]:
        __UpperCAmelCase							:			Union[str, Any]     =						{}  # To store graph: u -> (v,w)
        __UpperCAmelCase							:			Optional[int]     =						num  # Number of nodes in graph
        # To store the distance from source vertex
        __UpperCAmelCase							:			Optional[Any]     =						[0] * self.num_nodes
        __UpperCAmelCase							:			Dict     =						[-1] * self.num_nodes  # To store the path
      def 			UpperCAmelCase   (   self      :    Dict	,   __lowercase      :    Optional[int]	,   __lowercase      :    int	,   __lowercase      :    int      )							->   Tuple:
        #  Edge going from node u to v and v to u with weight w
        # u (w)-> v, v (w) -> u
        # Check if u already in graph
        if u in self.adjList:
          self.adjList[u].append((v, w)      )
        else:
          __UpperCAmelCase							:			int     =						[(v, w)]

        # Assuming undirected graph
        if v in self.adjList:
          self.adjList[v].append((u, w)      )
        else:
          __UpperCAmelCase							:			Union[str, Any]     =						[(u, w)]
      def 			UpperCAmelCase   (   self      :    Union[str, Any]      )							->   Union[str, Any]:
        # u -> v(w)
        for u in self.adjList:
          print(__lowercase	,   """->"""	,   """ -> """.join(str(f"""{v}({w})"""      ) for v, w in self.adjList[u]      )      )
      def 			UpperCAmelCase   (   self      :    List[str]	,   __lowercase      :    str      )							->   Optional[Any]:
        # Flush old junk values in par[]
        __UpperCAmelCase							:			Tuple     =						[-1] * self.num_nodes
        # src is the source node
        __UpperCAmelCase							:			Optional[Any]     =						0
        __UpperCAmelCase							:			Union[str, Any]     =						PriorityQueue()
        q.insert((0, src)      )  # (dist from src, node)
        for u in self.adjList:
          if u != src:
            __UpperCAmelCase							:			List[str]     =						sys.maxsize  # Infinity
            __UpperCAmelCase							:			int     =						-1

        while not q.is_empty():
          __UpperCAmelCase							:			Dict     =						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]:
            __UpperCAmelCase							:			Optional[Any]     =						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      )
              __UpperCAmelCase							:			str     =						new_dist
              __UpperCAmelCase							:			Dict     =						u

        # Show the shortest distances from src
        self.show_distances(__lowercase      )
      def 			UpperCAmelCase   (   self      :    Union[str, Any]	,   __lowercase      :    Optional[int]      )							->   Union[str, Any]:
        print(f"""Distance from node: {src}"""      )
        for u in range(self.num_nodes      ):
          print(f"""Node {u} has distance: {self.dist[u]}"""      )




      def 			UpperCAmelCase   (   self      :    str	,   __lowercase      :    Optional[int]	,   __lowercase      :    List[str]      )							->   Optional[Any]:
        # To show the shortest path from src to dest
        # WARNING: Use it *after* calling dijkstra
        __UpperCAmelCase							:			str     =						[]
        __UpperCAmelCase							:			Optional[int]     =						0
        __UpperCAmelCase							:			List[str]     =						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
          __UpperCAmelCase							:			Optional[Any]     =						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__":
       a	: Optional[int]      =				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










class 					a					:



      """simple docstring"""


      def __init__(   self      :    int	,   __lowercase      :    int      )							->   None:
        __UpperCAmelCase							:			str     =						data
        __UpperCAmelCase							:			BinaryTreeNode | None     =						None
        __UpperCAmelCase							:			BinaryTreeNode | None     =						None






def        lowerCamelCase__   (					__lowerCamelCase    :  BinaryTreeNode | None						,	__lowerCamelCase    :  int	):
  if node is None:
    __UpperCAmelCase							:			Optional[int]     =						BinaryTreeNode(__lowerCamelCase	)
    return node

  # binary search tree is not empty,
  # so we will insert it into the tree
  # if new_value is less than value of data in node,
  #  add it to left subtree and proceed recursively
  if new_value < node.data:
    __UpperCAmelCase							:			int     =						insert(node.left_child						,	__lowerCamelCase	)
  else:
    # if new_value is greater than value of data in node,
    #  add it to right subtree and proceed recursively
    __UpperCAmelCase							:			Dict     =						insert(node.right_child						,	__lowerCamelCase	)
  return node






def        lowerCamelCase__   (					__lowerCamelCase    :  None | BinaryTreeNode	):  # if node is None,return
  if node:
    __UpperCAmelCase							:			Optional[Any]     =						inorder(node.left_child	)
    __UpperCAmelCase							:			str     =						[*inorder_array, node.data]
    __UpperCAmelCase							:			Optional[Any]     =						inorder_array + inorder(node.right_child	)
  else:
    __UpperCAmelCase							:			Tuple     =						[]
  return inorder_array






def        lowerCamelCase__   (					):
  __UpperCAmelCase							:			Any     =						insert(__lowerCamelCase						,	15	)
  insert(__lowerCamelCase						,	10	)
  insert(__lowerCamelCase						,	25	)
  insert(__lowerCamelCase						,	6	)
  insert(__lowerCamelCase						,	14	)
  insert(__lowerCamelCase						,	20	)
  insert(__lowerCamelCase						,	60	)
  return root






def        lowerCamelCase__   (					):
  # main function
  __UpperCAmelCase							:			int     =						make_tree()
  print("""Printing values of binary search tree in Inorder Traversal."""	)
  inorder(__lowerCamelCase	)


if __name__ == "__main__":
       import doctest

       doctest.testmod()
       main()


