Algoritmo di Dijkstra TLE

Ciao, ho provato a risolvere CSES - Shortest Routes I ma putroppo mi va in TLE su quasi tutti i testcase. Credo sia un problema di fattore costante, perché sono sicura che la complessità sia O(m\log m) e in locale ci mette circa 5 secondi. Qualcuno potrebbe aiutarmi?

import Data.Functor ((<&>))
import Data.Map qualified as Map
import Data.Maybe (fromJust, isNothing, maybeToList)
import Data.Set qualified as Set
 
data BinomialTree a = BinomialTree {root :: a, children :: [BinomialTree a]} deriving (Show)
 
newtype BinomialHeap a = BinomialHeap [Maybe (BinomialTree a)] deriving (Show)
 
safeSplit :: [Maybe a] -> (Maybe a, [Maybe a])
safeSplit [] = (Nothing, [])
safeSplit (x : xs) = (x, xs)
 
mergeTree :: (Ord a) => BinomialTree a -> BinomialTree a -> BinomialTree a
mergeTree a b
  | root a <= root b = BinomialTree (root a) (b : children a)
  | otherwise = BinomialTree (root b) (a : children b)
 
mergeHeaps :: (Ord a) => BinomialHeap a -> BinomialHeap a -> BinomialHeap a
mergeHeaps (BinomialHeap a) (BinomialHeap b) = BinomialHeap (dropWhile isNothing . reverse $ mergeLists Nothing (reverse a) (reverse b))
  where
    mergeLists Nothing [] [] = []
    mergeLists carry [] [] = [carry]
    mergeLists carry a b =
      let (headA, tailA) = safeSplit a
          (headB, tailB) = safeSplit b
          (x, y, z) = reorder carry headA headB
          (digit, newCarry)
            | isNothing y = (x, Nothing)
            | otherwise = (z, Just $ mergeTree (fromJust x) (fromJust y))
       in digit : mergeLists newCarry tailA tailB
    reorder Nothing Nothing Nothing = (Nothing, Nothing, Nothing)
    reorder (Just x) Nothing Nothing = (Just x, Nothing, Nothing)
    reorder Nothing (Just x) Nothing = (Just x, Nothing, Nothing)
    reorder Nothing Nothing (Just x) = (Just x, Nothing, Nothing)
    reorder (Just x) (Just y) Nothing = (Just x, Just y, Nothing)
    reorder (Just x) Nothing (Just y) = (Just x, Just y, Nothing)
    reorder Nothing (Just x) (Just y) = (Just x, Just y, Nothing)
    reorder (Just x) (Just y) (Just z) = (Just x, Just y, Just z)
 
emptyHeap :: BinomialHeap a
emptyHeap = BinomialHeap []
 
isEmptyHeap :: BinomialHeap a -> Bool
isEmptyHeap (BinomialHeap x) = null x
 
singletonHeap :: a -> BinomialHeap a
singletonHeap x = BinomialHeap [Just (BinomialTree x [])]
 
pushHeap :: (Ord a) => a -> BinomialHeap a -> BinomialHeap a
pushHeap x = mergeHeaps (singletonHeap x)
 
popHeap :: (Ord a) => BinomialHeap a -> (Maybe a, BinomialHeap a)
popHeap heap
  | isEmptyHeap heap = (Nothing, heap)
  | otherwise = (Just heapMin, heapNew)
  where
    trees = (\(BinomialHeap trees) -> trees) heap
    minIdx = getMinIdx trees 0 Nothing Nothing
    getMinIdx [] _ _ minIdx = minIdx
    getMinIdx (x : xs) i min minIdx
      | isNothing min = getMinIdx xs (i + 1) (x >>= Just . root) (Just i)
      | isNothing x || root (fromJust x) >= fromJust min = getMinIdx xs (i + 1) min minIdx
      | otherwise = getMinIdx xs (i + 1) (x >>= Just . root) (Just i)
    fst = take (fromJust minIdx) trees
    snd = trees !! fromJust minIdx
    trd = drop (1 + fromJust minIdx) trees
    heapA = BinomialHeap (dropWhile isNothing (fst <> [Nothing] <> trd))
    heapB = BinomialHeap (map Just (children $ fromJust snd))
    heapNew = mergeHeaps heapA heapB
    heapMin = root $ fromJust snd
 
dijkstra :: Map.Map Int [(Int, Int)] -> Set.Set Int -> BinomialHeap (Int, Int) -> Map.Map Int Int -> Map.Map Int Int
dijkstra adj vis q ans
  | isEmptyHeap q = ans
  | Set.member top vis = dijkstra adj vis rest ans
  | otherwise = dijkstra adj (Set.insert top vis) (foldr (\(x, w) q -> pushHeap (dst + w, x) q) rest $ Map.findWithDefault [] top adj) (Map.insert top dst ans)
  where
    (Just (dst, top), rest) = popHeap q
 
solve :: Map.Map Int [(Int, Int)] -> Map.Map Int Int
solve adj = dijkstra adj Set.empty (singletonHeap (0, 0)) Map.empty
 
getAdj :: Int -> IO (Map.Map Int [(Int, Int)])
getAdj 0 = return Map.empty
getAdj i = getAdj (i - 1) >>= (\adj -> getLine <&> insert adj . map read . words)
  where
    insert adj [a, b, c] = case Map.lookup (a - 1) adj of
      Nothing -> Map.insert (a - 1) [(b - 1, c)] adj
      Just list -> Map.insert (a - 1) ((b - 1, c) : list) adj
 
main :: IO ()
main = getLine >>= (\[n, m] -> getAdj m >>= foldl (\y x -> y >> putStr (show x <> " ")) (return ()) . solve) . map read . words

6 Mi Piace