{- Author: Robin Nittka -}
{-# OPTIONS_GHC -O2 #-}

module Main
	where

import System.IO
import Control.Monad.ST
import Data.Array.ST
import Data.STRef
import Data.List

gras :: [String] -> [(Int,[(Int,(Int,Int))])]
gras [] = []
gras (line:xs) = (m, sort $ map (mkTuple3 . map read . words) a):gras b
	where
		[m,n] = map read $ words line
		(a,b) = splitAt n xs
		mkTuple3 [x,y,w] = (w,(x,y))

par :: STArray s Int Int -> Int -> ST s Int
par uf i = do
	p <- readArray uf i
	if p == i then
			return p
		else do
			p' <- par uf p
			writeArray uf i p'
			return p'

unionFind :: STArray s Int Int -> Int -> Int -> ST s Bool
unionFind uf x y = do
	x' <- par uf x
	y' <- par uf y
	if x' == y' then
			return True
		else do
			writeArray uf x' y'
			return False


update :: STArray s Int Int -> STRef s Int -> Int -> (Int,Int) -> ST s ()
update uf cnt w (a,b) = do
	b <- unionFind uf a b
	if b then
			modifySTRef cnt (+w)
		else
			return ()


solve :: Int -> [(Int,(Int,Int))] -> Int
solve n edges = runST $ do
	uf <- newListArray (0,n-1) [0..n-1]
	res <- newSTRef 0
	mapM_ (uncurry $ update uf res) edges
	readSTRef res


main :: IO ()
main = openFile "dark.in" ReadMode >>= hGetContents >>= mapM_ (print . uncurry solve) . gras . init . lines
