






from __future__ import annotations

from queue import Queue




class        snake_case_					:

						"""simple docstring"""



						def __init__(self:				Tuple      )						->    None:




											'''simple docstring'''



											__a				:	dict[int, list[int]]			=				{}



						def 					UpperCAmelCase__				(self:				int      )						->    None:




											'''simple docstring'''



											for i in self.vertices:
																print(__UpperCAmelCase   ,				" : "   ,				" -> ".join([str(__UpperCAmelCase      ) for j in self.vertices[i]]      )      )



						def 					UpperCAmelCase__				(self:				Tuple   ,				__UpperCAmelCase:				int   ,				__UpperCAmelCase:				int      )						->    None:




											'''simple docstring'''



											if from_vertex in self.vertices:
																self.vertices[from_vertex].append(__UpperCAmelCase      )
											else:
																__a				:	List[str]			=				[to_vertex]



						def 					UpperCAmelCase__				(self:				Optional[int]   ,				__UpperCAmelCase:				int      )						->    set[int]:




											'''simple docstring'''



											__a				:	Any			=				set()

											# create a first in first out queue to store all the vertices for BFS
											__a				:	Queue			=				Queue()

											# mark the source node as visited and enqueue it
											visited.add(__UpperCAmelCase      )
											queue.put(__UpperCAmelCase      )

											while not queue.empty():
																__a				:	int			=				queue.get()

																# loop through all adjacent vertex and enqueue it if not yet visited
																for adjacent_vertex in self.vertices[vertex]:
																					if adjacent_vertex not in visited:
																										queue.put(__UpperCAmelCase      )
																										visited.add(__UpperCAmelCase      )
											return visited


if __name__ == "__main__":
			from doctest import testmod

			testmod(verbose=True)

			UpperCAmelCase__			 =	Graph()
			g.add_edge(0, 1)
			g.add_edge(0, 2)
			g.add_edge(1, 2)
			g.add_edge(2, 0)
			g.add_edge(2, 3)
			g.add_edge(3, 3)

			g.print_graph()
			# 0  :  1 -> 2
			# 1  :  2
			# 2  :  0 -> 3
			# 3  :  3

			assert sorted(g.bfs(2)) == [0, 1, 2, 3]













def 						a_      (__A							,					__A			)							->	list[tuple[int, int, int]]:



					"""simple docstring"""
					__a				:	str			=				sorted(__A							,					key=lambda __A			: edge[2]			)

					__a				:	int			=				list(range(__A			)			)

					def find_parent(__A			):
										if i != parent[i]:
															__a				:	Optional[Any]			=				find_parent(parent[i]			)
										return parent[i]

					__a				:	Any			=				0
					__a				:	Optional[int]			=				[]

					for edge in edges:
										__a				:	Any			=				find_parent(edge[0]			)
										__a				:	Optional[Any]			=				find_parent(edge[1]			)
										if parent_a != parent_b:
															minimum_spanning_tree_cost += edge[2]
															minimum_spanning_tree.append(__A			)
															__a				:	List[str]			=				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)





