

import math
import sys






class 							A_			:


     def __init__(							self      :		Optional[Any] )							->     Dict:
      __lowerCAmelCase:       Union[str, Any]            =				0
      __lowerCAmelCase:       List[Any]            =				[]
      __lowerCAmelCase:       List[str]            =				{}  # To store the pos of node in array


     def   UpperCAmelCase  (							self      :		Any )							->     str:
      return self.cur_size == 0


     def   UpperCAmelCase  (							self      :		Union[str, Any]      ,  UpperCAmelCase      :		Tuple )							->     Union[str, Any]:
      __lowerCAmelCase:       int            =				self.left(UpperCAmelCase )
      __lowerCAmelCase:       List[str]            =				self.right(UpperCAmelCase )
      if lc < self.cur_size and self.array(UpperCAmelCase )[0] < self.array(UpperCAmelCase )[0]:
       __lowerCAmelCase:       Any            =				lc
      else:
       __lowerCAmelCase:       Any            =				idx
      if rc < self.cur_size and self.array(UpperCAmelCase )[0] < self.array(UpperCAmelCase )[0]:
       __lowerCAmelCase:       List[str]            =				rc
      if smallest != idx:
       self.swap(UpperCAmelCase      ,  UpperCAmelCase )
       self.min_heapify(UpperCAmelCase )


     def   UpperCAmelCase  (							self      :		List[str]      ,  UpperCAmelCase      :		str )							->     Optional[Any]:
      # Inserts a node into the Priority Queue
      __lowerCAmelCase:       Tuple            =				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      :		List[Any] )							->     str:
      # Removes and returns the min element at top of priority queue
      __lowerCAmelCase:       List[Any]            =				self.array[0][1]
      __lowerCAmelCase:       List[str]            =				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      :		Optional[int]      ,  UpperCAmelCase      :		List[Any] )							->     Union[str, Any]:
      # returns the index of left child
      return 2 * i + 1


     def   UpperCAmelCase  (							self      :		int      ,  UpperCAmelCase      :		List[Any] )							->     int:
      # returns the index of right child
      return 2 * i + 2


     def   UpperCAmelCase  (							self      :		int      ,  UpperCAmelCase      :		List[Any] )							->     Any:
      # returns the index of parent
      return math.floor(i / 2 )


     def   UpperCAmelCase  (							self      :		Union[str, Any]      ,  UpperCAmelCase      :		Dict      ,  UpperCAmelCase      :		Optional[Any] )							->     Optional[int]:
      # swaps array elements at indices i and j
      # update the pos{}
      __lowerCAmelCase:       int            =				j
      __lowerCAmelCase:       str            =				i
      __lowerCAmelCase:       Tuple            =				self.array[i]
      __lowerCAmelCase:       List[str]            =				self.array[j]
      __lowerCAmelCase:       Dict            =				temp


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







class 							A_			:


     def __init__(							self      :		Any      ,  UpperCAmelCase      :		Any )							->     int:
      __lowerCAmelCase:       Optional[int]            =				{}  # To store graph: u -> (v,w)
      __lowerCAmelCase:       Optional[int]            =				num  # Number of nodes in graph
      # To store the distance from source vertex
      __lowerCAmelCase:       List[str]            =				[0] * self.num_nodes
      __lowerCAmelCase:       Any            =				[-1] * self.num_nodes  # To store the path


     def   UpperCAmelCase  (							self      :		Optional[int]      ,  UpperCAmelCase      :		Optional[int]      ,  UpperCAmelCase      :		Optional[Any]      ,  UpperCAmelCase      :		Optional[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:
       __lowerCAmelCase:       List[Any]            =				[(v, w)]

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


     def   UpperCAmelCase  (							self      :		str )							->     Union[str, Any]:
      # u -> v(w)
      for u in self.adjList:
       print(UpperCAmelCase      ,  '->'      ,  ' -> '.join(str(F'''{v}({w})''' ) for v, w in self.adjList[u] ) )


     def   UpperCAmelCase  (							self      :		str      ,  UpperCAmelCase      :		Optional[Any] )							->     List[Any]:
      # Flush old junk values in par[]
      __lowerCAmelCase:       List[Any]            =				[-1] * self.num_nodes
      # src is the source node
      __lowerCAmelCase:       str            =				0
      __lowerCAmelCase:       Tuple            =				PriorityQueue()
      q.insert((0, src) )  # (dist from src, node)
      for u in self.adjList:
       if u != src:
        __lowerCAmelCase:       Optional[Any]            =				sys.maxsize  # Infinity
        __lowerCAmelCase:       List[Any]            =				-1

      while not q.is_empty():
       __lowerCAmelCase:       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]:
        __lowerCAmelCase:       Dict            =				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)      ,  UpperCAmelCase )
         __lowerCAmelCase:       Tuple            =				new_dist
         __lowerCAmelCase:       Any            =				u

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


     def   UpperCAmelCase  (							self      :		Union[str, Any]      ,  UpperCAmelCase      :		int )							->     Tuple:
      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      :		List[str]      ,  UpperCAmelCase      :		Any      ,  UpperCAmelCase      :		Optional[Any] )							->     Optional[int]:
      # To show the shortest path from src to dest
      # WARNING: Use it *after* calling dijkstra
      __lowerCAmelCase:       Optional[int]            =				[]
      __lowerCAmelCase:       Optional[int]            =				0
      __lowerCAmelCase:       Tuple            =				dest
      # Backtracking from dest to src
      while self.par[temp] != -1:
       path.append(UpperCAmelCase )
       if temp != src:
        for v, w in self.adjList[temp]:
         if v == self.par[temp]:
          cost += w
          break
       __lowerCAmelCase:       Optional[Any]            =				self.par[temp]
      path.append(UpperCAmelCase )
      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: '      ,  UpperCAmelCase )


if __name__ == "__main__":
  _a			=       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, 1_1)
  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, 1_4)
  graph.add_edge(4, 5, 1_0)
  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








from __future__ import annotations

from collections.abc import Iterable
from dataclasses import dataclass
from typing import Any






class 							A_			:
     _lowercase      :					Any       =     ('_front', '_back', '_len')






     @dataclass
     class 							A_			:
          _lowercase      :					Any       =     None
          _lowercase      :					Deque._Node | None       =     None
          _lowercase      :					Deque._Node | None       =     None







     class 							A_			:
          _lowercase      :					Optional[Any]       =     ('_cur',)


          def __init__(							self      :		Any      ,  UpperCAmelCase      :		Deque._Node | None )							->     None:
           __lowerCAmelCase:       int            =				cur


          def __iter__(							self      :		int )							->     Deque._Iterator:
           return self


          def   UpperCAmelCase  (							self      :		Optional[Any] )							->     Any:
           if self._cur is None:
            # finished iterating
            raise StopIteration
           __lowerCAmelCase:       Optional[Any]            =				self._cur.val
           __lowerCAmelCase:       List[Any]            =				self._cur.next_node

           return val







     def __init__(							self      :		Any      ,  UpperCAmelCase      :		Iterable[Any] | None = None )							->     None:
      __lowerCAmelCase:       Any            =				None
      __lowerCAmelCase:       Any            =				None
      __lowerCAmelCase:       int            =				0

      if iterable is not None:
       # append every value to the deque
       for val in iterable:
        self.append(UpperCAmelCase )


     def   UpperCAmelCase  (							self      :		List[str]      ,  UpperCAmelCase      :		Any )							->     None:
      __lowerCAmelCase:       Union[str, Any]            =				self._Node(UpperCAmelCase      ,  UpperCAmelCase      ,  UpperCAmelCase )
      if self.is_empty():
       # front = back
       __lowerCAmelCase:       int            =				node
       __lowerCAmelCase:       List[Any]            =				1
      else:
       # connect nodes
       __lowerCAmelCase:       Optional[Any]            =				node
       __lowerCAmelCase:       str            =				self._back
       __lowerCAmelCase:       Optional[int]            =				node  # assign new back to the new node

       self._len += 1

       # make sure there were no errors
       assert not self.is_empty(), "Error on appending value."


     def   UpperCAmelCase  (							self      :		Optional[int]      ,  UpperCAmelCase      :		Any )							->     None:
      __lowerCAmelCase:       int            =				self._Node(UpperCAmelCase      ,  UpperCAmelCase      ,  UpperCAmelCase )
      if self.is_empty():
       # front = back
       __lowerCAmelCase:       Union[str, Any]            =				node
       __lowerCAmelCase:       str            =				1
      else:
       # connect nodes
       __lowerCAmelCase:       Dict            =				self._front
       __lowerCAmelCase:       Optional[int]            =				node
       __lowerCAmelCase:       Any            =				node  # assign new front to the new node

       self._len += 1

       # make sure there were no errors
       assert not self.is_empty(), "Error on appending value."


     def   UpperCAmelCase  (							self      :		Union[str, Any]      ,  UpperCAmelCase      :		Iterable[Any] )							->     None:
      for val in iterable:
       self.append(UpperCAmelCase )


     def   UpperCAmelCase  (							self      :		List[str]      ,  UpperCAmelCase      :		Iterable[Any] )							->     None:
      for val in iterable:
       self.appendleft(UpperCAmelCase )


     def   UpperCAmelCase  (							self      :		Dict )							->     Any:
      assert not self.is_empty(), "Deque is empty."

      __lowerCAmelCase:       Optional[int]            =				self._back
      __lowerCAmelCase:       Optional[Any]            =				self._back.prev_node  # set new back
      # drop the last node - python will deallocate memory automatically
      __lowerCAmelCase:       Optional[int]            =				None

      self._len -= 1

      return topop.val


     def   UpperCAmelCase  (							self      :		Dict )							->     Any:
      assert not self.is_empty(), "Deque is empty."

      __lowerCAmelCase:       Optional[Any]            =				self._front
      __lowerCAmelCase:       Optional[Any]            =				self._front.next_node  # set new front and drop the first node
      __lowerCAmelCase:       int            =				None

      self._len -= 1

      return topop.val


     def   UpperCAmelCase  (							self      :		Dict )							->     bool:
      return self._front is None


     def __len__(							self      :		List[Any] )							->     int:
      return self._len


     def __eq__(							self      :		Union[str, Any]      ,  UpperCAmelCase      :		object )							->     bool:

      if not isinstance(UpperCAmelCase      ,  UpperCAmelCase ):
       return NotImplemented

      __lowerCAmelCase:       List[Any]            =				self._front
      __lowerCAmelCase:       Dict            =				other._front

      # if the length of the dequeues are not the same, they are not equal
      if len(self ) != len(UpperCAmelCase ):
       return False

      while me is not None and oth is not None:
       # compare every value
       if me.val != oth.val:
        return False
       __lowerCAmelCase:       Optional[Any]            =				me.next_node
       __lowerCAmelCase:       Optional[Any]            =				oth.next_node

      return True


     def __iter__(							self      :		Tuple )							->     Deque._Iterator:
      return Deque._Iterator(self._front )


     def __repr__(							self      :		Optional[Any] )							->     str:
      __lowerCAmelCase:       Union[str, Any]            =				[]
      __lowerCAmelCase:       Optional[int]            =				self._front
      while aux is not None:
       # append the values in a list to display
       values_list.append(aux.val )
       __lowerCAmelCase:       Any            =				aux.next_node

      return F'''[{', '.join(repr(UpperCAmelCase ) for val in values_list )}]'''


if __name__ == "__main__":
  import doctest

  doctest.testmod()





