
'''simple docstring'''

import bisect
import copy
from collections import defaultdict

import numpy as np
from torch.utils.data import BatchSampler, Sampler

from utils import logger



def        SCREAMING_SNAKE_CASE_  (	snake_case_				:	Optional[int]   ,     snake_case_				:	Any							)       ->	Dict:
 SCREAMING_SNAKE_CASE  :  List[str]								=		copy.deepcopy(snake_case_							)
 SCREAMING_SNAKE_CASE  :  str								=		sorted(snake_case_							)
 SCREAMING_SNAKE_CASE  :  int								=		[bisect.bisect_right(snake_case_   ,     snake_case_							) for y in x]
 return quantized



def        SCREAMING_SNAKE_CASE_  (	snake_case_				:	Tuple   ,     snake_case_				:	Dict=0							)       ->	Tuple:
 SCREAMING_SNAKE_CASE  :  Optional[Any]								=		np.arange(start=3   ,     stop=snake_case_   ,     step=4							).tolist() if k > 0 else [10]
 SCREAMING_SNAKE_CASE  :  str								=		_quantize(snake_case_   ,     snake_case_							)
 # count number of elements per group
 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		np.unique(snake_case_   ,     return_counts=snake_case_							)[1]
 SCREAMING_SNAKE_CASE  :  Optional[Any]								=		[0] + bins + [np.inf]
 logger.info('Using {} as bins for aspect lengths quantization'.format(snake_case_							)							)
 logger.info('Count of instances per bin: {}'.format(snake_case_							)							)
 return groups





class 		_a     (							SCREAMING_SNAKE_CASE  ):







   """simple docstring"""




   def __init__(       self    ,__SCREAMING_SNAKE_CASE    ,__SCREAMING_SNAKE_CASE    ,__SCREAMING_SNAKE_CASE      ):
    if not isinstance(__SCREAMING_SNAKE_CASE    ,__SCREAMING_SNAKE_CASE      ):
     raise ValueError(
         'sampler should be an instance of torch.utils.data.Sampler, but got sampler={}'.format(__SCREAMING_SNAKE_CASE      )      )
    SCREAMING_SNAKE_CASE  :  List[Any]								=		sampler
    SCREAMING_SNAKE_CASE  :  Dict								=		group_ids
    SCREAMING_SNAKE_CASE  :  Any								=		batch_size






   def __iter__(       self      ):
    SCREAMING_SNAKE_CASE  :  Optional[Any]								=		defaultdict(__SCREAMING_SNAKE_CASE      )
    SCREAMING_SNAKE_CASE  :  List[str]								=		defaultdict(__SCREAMING_SNAKE_CASE      )

    SCREAMING_SNAKE_CASE  :  Any								=		0
    for idx in self.sampler:
     SCREAMING_SNAKE_CASE  :  List[Any]								=		self.group_ids[idx]
     buffer_per_group[group_id].append(__SCREAMING_SNAKE_CASE      )
     samples_per_group[group_id].append(__SCREAMING_SNAKE_CASE      )
     if len(buffer_per_group[group_id]      ) == self.batch_size:
      yield buffer_per_group[group_id]  # TODO
      num_batches += 1
      del buffer_per_group[group_id]
     assert len(buffer_per_group[group_id]      ) < self.batch_size

    # now we have run out of elements that satisfy
    # the group criteria, let's return the remaining
    # elements so that the size of the sampler is
    # deterministic
    SCREAMING_SNAKE_CASE  :  Optional[Any]								=		len(self      )
    SCREAMING_SNAKE_CASE  :  int								=		expected_num_batches - num_batches
    if num_remaining > 0:
     # for the remaining batches, group the batches by similar lengths
     SCREAMING_SNAKE_CASE  :  List[str]								=		[]
     for group_id, idxs in sorted(buffer_per_group.items()    ,key=lambda __SCREAMING_SNAKE_CASE      : x[0]      ):
      batch_idx.extend(__SCREAMING_SNAKE_CASE      )
      if len(__SCREAMING_SNAKE_CASE      ) >= self.batch_size:
       yield batch_idx[: self.batch_size]
       SCREAMING_SNAKE_CASE  :  List[Any]								=		batch_idx[self.batch_size :]
       num_remaining -= 1
     if len(__SCREAMING_SNAKE_CASE      ) > 0:
      yield batch_idx
      num_remaining -= 1
    assert num_remaining == 0






   def __len__(       self      ):
    return (len(self.sampler      ) + self.batch_size - 1) // self.batch_size




'''simple docstring'''

def        SCREAMING_SNAKE_CASE_  (	snake_case_				:	int   ,     snake_case_				:	list[tuple[int, int, int]]							)       ->	list[tuple[int, int, int]]:
 SCREAMING_SNAKE_CASE  :  List[Any]								=		sorted(snake_case_   ,     key=lambda snake_case_							: edge[2]							)

 SCREAMING_SNAKE_CASE  :  str								=		list(range(snake_case_							)							)

 def find_parent(snake_case_				:	Union[str, Any]							):
  if i != parent[i]:
   SCREAMING_SNAKE_CASE  :  int								=		find_parent(parent[i]							)
  return parent[i]

 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		0
 SCREAMING_SNAKE_CASE  :  Any								=		[]

 for edge in edges:
  SCREAMING_SNAKE_CASE  :  Dict								=		find_parent(edge[0]							)
  SCREAMING_SNAKE_CASE  :  Optional[int]								=		find_parent(edge[1]							)
  if parent_a != parent_b:
   minimum_spanning_tree_cost += edge[2]
   minimum_spanning_tree.append(snake_case_							)
   SCREAMING_SNAKE_CASE  :  Tuple								=		parent_b

 return minimum_spanning_tree


if __name__ == "__main__":  # pragma: no cover
   __UpperCAmelCase						,						__UpperCAmelCase												=   list(map(int, input().strip().split()))
   __UpperCAmelCase												=   []

   for _ in range(num_edges):
      __UpperCAmelCase						,						__UpperCAmelCase						,						__UpperCAmelCase												=   (int(x) for x in input().strip().split())
      edges.append((nodea, nodea, cost))

   kruskal(num_nodes, edges)


