import Data.IntMap.Strict ((!)) import qualified Data.IntMap.Strict as M import qualified Data.Set as S import qualified Data.ByteString.Char8 as B import Control.Monad import Data.Maybe import Data.List type Cost = Int type Vertex = Int type Heap = S.Set (Cost, Vertex) nullq = S.null empty = S.empty push c v = S.insert (c,v) pop = S.deleteFindMin main = do [n,_,s,g] <- map read . words <$> getLine es <- map (map (fst . fromJust . B.readInt) . B.words) . B.lines <$> B.getContents putStrLn $ unwords $ map show (route n s g es) route n s g es = unfoldr (backtrack imr) s ++ [g] where imr = dijkstra t im0 q0 t = foldl' (\acc [a,b,c] -> M.insertWith (++) b [(a,c)] (M.insertWith (++) a [(b,c)] acc)) M.empty es im0 = M.singleton g (0,[]) q0 = push 0 g empty backtrack im v = case im!v of (0,[]) -> Nothing (_,(vp:_)) -> Just (v,vp) dijkstra t im q | nullq q = im | otherwise = dijkstra t im' q'' where ((c0,v),q') = pop q im' = foldl' (\acc (b,c) -> M.insertWith mindic b (c0+c,[v]) acc) im vns q'' = foldl' (\acc (b,c) -> push (c0+c) b acc) q' vns vns = filter (\(b,c) -> M.notMember b im || c0+c <= fst (im!b)) (M.findWithDefault [] v t) mindic (c1,v1@[v]) (c2,v2) | c1 < c2 = (c1,v1) | c1 == c2 = (c1, insert v v2)