



import math
import sys



class 		_lowercase		:

   def __init__(   self      :							int				)							->					Union[str, Any]:


    """simple docstring"""






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

   def 		A				(   self      :							Union[str, Any]				)							->					str:


    """simple docstring"""






    return self.cur_size == 0

   def 		A				(   self      :							Optional[int]				, __lowerCAmelCase      :							str				)							->					str:


    """simple docstring"""






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

   def 		A				(   self      :							Optional[Any]				, __lowerCAmelCase      :							Union[str, Any]				)							->					int:


    """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 		A				(   self      :							Union[str, Any]				)							->					Dict:


    """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 		A				(   self      :							List[str]				, __lowerCAmelCase      :							int				)							->					Optional[Any]:


    """simple docstring"""






    return 2 * i + 1

   def 		A				(   self      :							Optional[int]				, __lowerCAmelCase      :							Any				)							->					Union[str, Any]:


    """simple docstring"""






    return 2 * i + 2

   def 		A				(   self      :							Tuple				, __lowerCAmelCase      :							str				)							->					List[str]:


    """simple docstring"""






    return math.floor(i / 2				)

   def 		A				(   self      :							Dict				, __lowerCAmelCase      :							int				, __lowerCAmelCase      :							Optional[int]				)							->					Optional[Any]:


    """simple docstring"""






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




   def 		A				(   self      :							Optional[int]				, __lowerCAmelCase      :							Any				, __lowerCAmelCase      :							Optional[Any]				)							->					Optional[Any]:


    """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(lowerCamelCase_				)][0] > self.array[idx][0]:
     self.swap(lowerCamelCase_				, self.par(lowerCamelCase_				)				)
     a							=		self.par(lowerCamelCase_				)



class 		_lowercase		:

   def __init__(   self      :							List[Any]				, __lowerCAmelCase      :							Union[str, Any]				)							->					List[str]:


    """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 		A				(   self      :							str				, __lowerCAmelCase      :							Optional[Any]				, __lowerCAmelCase      :							Union[str, Any]				, __lowerCAmelCase      :							str				)							->					int:


    """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 		A				(   self      :							Optional[Any]				)							->					Union[str, Any]:


    """simple docstring"""






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

   def 		A				(   self      :							Optional[int]				, __lowerCAmelCase      :							List[Any]				)							->					List[str]:


    """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)				, lowerCamelCase_				)
       a							=		new_dist
       a							=		u

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

   def 		A				(   self      :							Optional[int]				, __lowerCAmelCase      :							Any				)							->					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 		A				(   self      :							Optional[Any]				, __lowerCAmelCase      :							Dict				, __lowerCAmelCase      :							int				)							->					Tuple:


    """simple docstring"""






    a							=		[]
    a							=		0
    a							=		dest
    # Backtracking from dest to src
    while self.par[temp] != -1:
     path.append(lowerCamelCase_				)
     if temp != src:
      for v, w in self.adjList[temp]:
       if v == self.par[temp]:
        cost += w
        break
     a							=		self.par[temp]
    path.append(lowerCamelCase_				)
    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: "				, lowerCamelCase_				)


if __name__ == "__main__":
     A_		:  List[str]										=  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__						:

       def __init__( self   :  int   ,				lowerCamelCase_   :  int     ):
            a_     :  Dict				      =     data
            a_     :  int
            a_     :  Node



def 			_a      (    __UpperCamelCase			):
     a_     :  int				      =     0
     a_     :  Optional[Any]				      =     x



def 			_a      (    __UpperCamelCase	,	__UpperCamelCase			):
     a_      ,      a_     :  Dict				      =     find_set(__UpperCamelCase			), find_set(__UpperCamelCase			)
     if x == y:
          return

     elif x.rank > y.rank:
          a_     :  Tuple				      =     x
     else:
          a_     :  Optional[Any]				      =     y
          if x.rank == y.rank:
               y.rank += 1



def 			_a      (    __UpperCamelCase			):
     if x != x.parent:
          a_     :  Tuple				      =     find_set(x.parent			)
     return x.parent



def 			_a      (    __UpperCamelCase			):
     a_     :  List[Any]				      =     ({0, 1, 2}, {3, 4, 5})
     for s in sets:
          if node.data in s:
               return s
     a_     :  Union[str, Any]				      =     F'''{node.data} is not in {sets}'''
     raise ValueError(__UpperCamelCase			)



def 			_a      (    ):
     a_     :  int				      =     [Node(__UpperCamelCase			) for i in range(6			)]
     for v in vertex:
          make_set(__UpperCamelCase			)

     union_set(vertex[0]	,	vertex[1]			)
     union_set(vertex[1]	,	vertex[2]			)
     union_set(vertex[3]	,	vertex[4]			)
     union_set(vertex[3]	,	vertex[5]			)

     for nodea in vertex:
          for nodea in vertex:
               if find_python_set(__UpperCamelCase			).isdisjoint(find_python_set(__UpperCamelCase			)			):
                    assert find_set(__UpperCamelCase			) != find_set(__UpperCamelCase			)
               else:
                    assert find_set(__UpperCamelCase			) == find_set(__UpperCamelCase			)


if __name__ == "__main__":
       test_disjoint_set()



