#if __GLASGOW_HASKELL__
#endif
#if __GLASGOW_HASKELL__ >= 703
#endif
#include "containers.h"
module Data.Graph(
        
        
        stronglyConnComp, stronglyConnCompR, SCC(..), flattenSCC, flattenSCCs,
        
        Graph, Table, Bounds, Edge, Vertex,
        
        graphFromEdges, graphFromEdges', buildG, transposeG,
        
        
        vertices, edges,
        outdegree, indegree,
        
        dfs, dff,
        topSort,
        components,
        scc,
        bcc,
        
        reachable, path,
        module Data.Tree
    ) where
#if __GLASGOW_HASKELL__
# define USE_ST_MONAD 1
#endif
#if USE_ST_MONAD
import Control.Monad.ST
import Data.Array.ST (STArray, newArray, readArray, writeArray)
#else
import Data.IntSet (IntSet)
import qualified Data.IntSet as Set
#endif
import Data.Tree (Tree(Node), Forest)
import Control.Applicative
import Control.DeepSeq (NFData(rnf))
import Data.Maybe
import Data.Array
import Data.List
data SCC vertex = AcyclicSCC vertex     
                                        
                | CyclicSCC  [vertex]   
                                        
instance NFData a => NFData (SCC a) where
    rnf (AcyclicSCC v) = rnf v
    rnf (CyclicSCC vs) = rnf vs
instance Functor SCC where
    fmap f (AcyclicSCC v) = AcyclicSCC (f v)
    fmap f (CyclicSCC vs) = CyclicSCC (fmap f vs)
flattenSCCs :: [SCC a] -> [a]
flattenSCCs = concatMap flattenSCC
flattenSCC :: SCC vertex -> [vertex]
flattenSCC (AcyclicSCC v) = [v]
flattenSCC (CyclicSCC vs) = vs
stronglyConnComp
        :: Ord key
        => [(node, key, [key])]
                
                
                
                
        -> [SCC node]
stronglyConnComp edges0
  = map get_node (stronglyConnCompR edges0)
  where
    get_node (AcyclicSCC (n, _, _)) = AcyclicSCC n
    get_node (CyclicSCC triples)     = CyclicSCC [n | (n,_,_) <- triples]
stronglyConnCompR
        :: Ord key
        => [(node, key, [key])]
                
                
                
                
        -> [SCC (node, key, [key])]     
stronglyConnCompR [] = []  
stronglyConnCompR edges0
  = map decode forest
  where
    (graph, vertex_fn,_) = graphFromEdges edges0
    forest             = scc graph
    decode (Node v []) | mentions_itself v = CyclicSCC [vertex_fn v]
                       | otherwise         = AcyclicSCC (vertex_fn v)
    decode other = CyclicSCC (dec other [])
                 where
                   dec (Node v ts) vs = vertex_fn v : foldr dec vs ts
    mentions_itself v = v `elem` (graph ! v)
type Vertex  = Int
type Table a = Array Vertex a
type Graph   = Table [Vertex]
type Bounds  = (Vertex, Vertex)
type Edge    = (Vertex, Vertex)
vertices :: Graph -> [Vertex]
vertices  = indices
edges    :: Graph -> [Edge]
edges g   = [ (v, w) | v <- vertices g, w <- g!v ]
mapT    :: (Vertex -> a -> b) -> Table a -> Table b
mapT f t = array (bounds t) [ (,) v (f v (t!v)) | v <- indices t ]
buildG :: Bounds -> [Edge] -> Graph
buildG bounds0 edges0 = accumArray (flip (:)) [] bounds0 edges0
transposeG  :: Graph -> Graph
transposeG g = buildG (bounds g) (reverseE g)
reverseE    :: Graph -> [Edge]
reverseE g   = [ (w, v) | (v, w) <- edges g ]
outdegree :: Graph -> Table Int
outdegree  = mapT numEdges
             where numEdges _ ws = length ws
indegree :: Graph -> Table Int
indegree  = outdegree . transposeG
graphFromEdges'
        :: Ord key
        => [(node, key, [key])]
        -> (Graph, Vertex -> (node, key, [key]))
graphFromEdges' x = (a,b) where
    (a,b,_) = graphFromEdges x
graphFromEdges
        :: Ord key
        => [(node, key, [key])]
        -> (Graph, Vertex -> (node, key, [key]), key -> Maybe Vertex)
graphFromEdges edges0
  = (graph, \v -> vertex_map ! v, key_vertex)
  where
    max_v           = length edges0  1
    bounds0         = (0,max_v) :: (Vertex, Vertex)
    sorted_edges    = sortBy lt edges0
    edges1          = zipWith (,) [0..] sorted_edges
    graph           = array bounds0 [(,) v (mapMaybe key_vertex ks) | (,) v (_,    _, ks) <- edges1]
    key_map         = array bounds0 [(,) v k                       | (,) v (_,    k, _ ) <- edges1]
    vertex_map      = array bounds0 edges1
    (_,k1,_) `lt` (_,k2,_) = k1 `compare` k2
    
    
    key_vertex k   = findVertex 0 max_v
                   where
                     findVertex a b | a > b
                              = Nothing
                     findVertex a b = case compare k (key_map ! mid) of
                                   LT -> findVertex a (mid1)
                                   EQ -> Just mid
                                   GT -> findVertex (mid+1) b
                              where
                                mid = a + (b  a) `div` 2
dff          :: Graph -> Forest Vertex
dff g         = dfs g (vertices g)
dfs          :: Graph -> [Vertex] -> Forest Vertex
dfs g vs      = prune (bounds g) (map (generate g) vs)
generate     :: Graph -> Vertex -> Tree Vertex
generate g v  = Node v (map (generate g) (g!v))
prune        :: Bounds -> Forest Vertex -> Forest Vertex
prune bnds ts = run bnds (chop ts)
chop         :: Forest Vertex -> SetM s (Forest Vertex)
chop []       = return []
chop (Node v ts : us)
              = do
                visited <- contains v
                if visited then
                  chop us
                 else do
                  include v
                  as <- chop ts
                  bs <- chop us
                  return (Node v as : bs)
#if USE_ST_MONAD
newtype SetM s a = SetM { runSetM :: STArray s Vertex Bool -> ST s a }
instance Monad (SetM s) where
    return x     = SetM $ const (return x)
    
    SetM v >>= f = SetM $ \s -> do { x <- v s; runSetM (f x) s }
    
instance Functor (SetM s) where
    f `fmap` SetM v = SetM $ \s -> f `fmap` v s
    
instance Applicative (SetM s) where
    pure x = SetM $ const (return x)
    
    SetM f <*> SetM v = SetM $ \s -> f s >>= (`fmap` v s)
    
    
    
    
run          :: Bounds -> (forall s. SetM s a) -> a
run bnds act  = runST (newArray bnds False >>= runSetM act)
contains     :: Vertex -> SetM s Bool
contains v    = SetM $ \ m -> readArray m v
include      :: Vertex -> SetM s ()
include v     = SetM $ \ m -> writeArray m v True
#else /* !USE_ST_MONAD */
newtype SetM s a = SetM { runSetM :: IntSet -> (a, IntSet) }
instance Monad (SetM s) where
    return x     = SetM $ \s -> (x, s)
    SetM v >>= f = SetM $ \s -> case v s of (x, s') -> runSetM (f x) s'
instance Functor (SetM s) where
    f `fmap` SetM v = SetM $ \s -> case v s of (x, s') -> (f x, s')
    
instance Applicative (SetM s) where
    pure x = SetM $ \s -> (x, s)
    
    SetM f <*> SetM v = SetM $ \s -> case f s of (k, s') -> case v s' of (x, s'') -> (k x, s'')
    
run          :: Bounds -> SetM s a -> a
run _ act     = fst (runSetM act Set.empty)
contains     :: Vertex -> SetM s Bool
contains v    = SetM $ \ m -> (Set.member v m, m)
include      :: Vertex -> SetM s ()
include v     = SetM $ \ m -> ((), Set.insert v m)
#endif /* !USE_ST_MONAD */
preorder' :: Tree a -> [a] -> [a]
preorder' (Node a ts) = (a :) . preorderF' ts
preorderF' :: Forest a -> [a] -> [a]
preorderF' ts = foldr (.) id $ map preorder' ts
preorderF :: Forest a -> [a]
preorderF ts = preorderF' ts []
tabulate        :: Bounds -> [Vertex] -> Table Int
tabulate bnds vs = array bnds (zipWith (,) vs [1..])
preArr          :: Bounds -> Forest Vertex -> Table Int
preArr bnds      = tabulate bnds . preorderF
postorder :: Tree a -> [a] -> [a]
postorder (Node a ts) = postorderF ts . (a :)
postorderF   :: Forest a -> [a] -> [a]
postorderF ts = foldr (.) id $ map postorder ts
postOrd :: Graph -> [Vertex]
postOrd g = postorderF (dff g) []
topSort      :: Graph -> [Vertex]
topSort       = reverse . postOrd
components   :: Graph -> Forest Vertex
components    = dff . undirected
undirected   :: Graph -> Graph
undirected g  = buildG (bounds g) (edges g ++ reverseE g)
scc  :: Graph -> Forest Vertex
scc g = dfs g (reverse (postOrd (transposeG g)))
reachable    :: Graph -> Vertex -> [Vertex]
reachable g v = preorderF (dfs g [v])
path         :: Graph -> Vertex -> Vertex -> Bool
path g v w    = w `elem` (reachable g v)
bcc :: Graph -> Forest [Vertex]
bcc g = (concat . map bicomps . map (do_label g dnum)) forest
 where forest = dff g
       dnum   = preArr (bounds g) forest
do_label :: Graph -> Table Int -> Tree Vertex -> Tree (Vertex,Int,Int)
do_label g dnum (Node v ts) = Node (v,dnum!v,lv) us
 where us = map (do_label g dnum) ts
       lv = minimum ([dnum!v] ++ [dnum!w | w <- g!v]
                     ++ [lu | Node (_,_,lu) _ <- us])
bicomps :: Tree (Vertex,Int,Int) -> Forest [Vertex]
bicomps (Node (v,_,_) ts)
      = [ Node (v:vs) us | (_,Node vs us) <- map collect ts]
collect :: Tree (Vertex,Int,Int) -> (Int, Tree [Vertex])
collect (Node (v,dv,lv) ts) = (lv, Node (v:vs) cs)
 where collected = map collect ts
       vs = concat [ ws | (lw, Node ws _) <- collected, lw<dv]
       cs = concat [ if lw<dv then us else [Node (v:ws) us]
                        | (lw, Node ws us) <- collected ]