{- 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