Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- {-# LANGUAGE OverloadedStrings #-}
- module Main (
- main
- ) where
- import Control.Applicative
- import Data.Maybe (fromMaybe)
- import Data.Foldable
- import qualified Data.Map as M
- import qualified Data.Set as S
- import Data.Text (Text)
- import qualified Data.Text.IO as TIO
- import Data.Attoparsec.Text hiding (parse)
- type AdjMap a = M.Map a [a]
- graphNext :: Ord a => AdjMap a -> a -> [a]
- graphNext graph x = fromMaybe [] $ M.lookup x graph
- parse :: Text -> AdjMap Int
- parse x =
- case parseOnly (M.fromList <$> many (pipe <* endOfLine)) x of
- Left _ -> M.empty
- Right z -> z
- where
- pipe :: Parser (Int, [Int])
- pipe =
- (,) <$> (decimal <* skipSpace) <*>
- (string "<->" *> skipSpace *> (decimal `sepBy` (char ',' *> skipSpace)))
- dfs :: Ord a => (a -> [a]) -> a -> S.Set a
- dfs next start = go S.empty [start]
- where
- go visited [] = visited
- go visited (x:xs)
- | x `S.member` visited = go visited xs
- | otherwise = go (x `S.insert` visited) (next x ++ xs)
- sccs :: Ord a => AdjMap a -> [S.Set a]
- sccs graph
- | M.null graph = []
- | otherwise =
- let start = fst $ M.findMin graph
- scc = dfs (graphNext graph) start
- in scc : sccs (foldl' (flip M.delete) graph scc)
- main :: IO ()
- main = do
- input <- parse <$> TIO.getContents
- print . S.size . dfs (graphNext input) $ 0
- print . length . sccs $ input
Add Comment
Please, Sign In to add comment