diff --git a/comfort-graph.cabal b/comfort-graph.cabal
--- a/comfort-graph.cabal
+++ b/comfort-graph.cabal
@@ -1,5 +1,5 @@
 Name:                comfort-graph
-Version:             0.0.4.1
+Version:             0.0.5
 Synopsis:            Graph structure with type parameters for nodes and edges
 Description:
   This graph structure is based on "Data.Map"
@@ -60,7 +60,7 @@
   Makefile
 
 Source-Repository this
-  Tag:         0.0.4.1
+  Tag:         0.0.5
   Type:        darcs
   Location:    https://hub.darcs.net/thielema/comfort-graph
 
@@ -79,7 +79,8 @@
     QuickCheck >=2.5 && <3,
     containers >=0.5.8 && <0.9,
     transformers >=0.5 && <0.7,
-    semigroups >=0.1 && <1.0,
+    non-empty >=0.3 && <0.4,
+    semigroups >=0.1 && <1,
     utility-ht >=0.0.10 && <0.1,
     base >=4.5 && <5
   Hs-Source-Dirs:      src
@@ -95,6 +96,7 @@
   Other-Modules:
     Test.Base
     Test.Data.Graph.Comfort
+    Test.Data.Graph.Alternative
   Build-Depends:
     comfort-graph,
     doctest-lib >=0.1 && <0.2,
@@ -102,6 +104,7 @@
     QuickCheck >=2 && <3,
     transformers,
     containers,
+    non-empty,
     utility-ht,
     base
   Default-Language:    Haskell2010
diff --git a/src/Data/Graph/Comfort.hs b/src/Data/Graph/Comfort.hs
--- a/src/Data/Graph/Comfort.hs
+++ b/src/Data/Graph/Comfort.hs
@@ -10,6 +10,7 @@
 
    -- * Construction
    empty, fromList, fromMap,
+   fromTree, fromForest,
 
    -- * Extract large portions of the graph
    graphMap,
@@ -28,6 +29,7 @@
    components,
    isConsistent,
    stronglyConnectedComponents,
+   stronglyConnectedComponentsNE,
 
    -- * Manipulate labels
    mapNode, mapNodeWithKey,
@@ -63,6 +65,7 @@
 import Data.Functor.Classes
          (Eq1(liftEq), Ord1(liftCompare), Show1(liftShowsPrec))
 
+import qualified Data.NonEmpty.Set as NonEmptySet
 import qualified Data.Map as Map
 import qualified Data.Set as Set
 import qualified Data.Tree as Tree
@@ -73,7 +76,8 @@
 import Data.Set (Set)
 import Data.Tree (Tree, Forest)
 import Data.Monoid
-         (Monoid, mempty, mappend, All(All), getAll, Endo(Endo), appEndo)
+         (Monoid, mempty, mappend, mconcat,
+          All(All), getAll, Endo(Endo), appEndo)
 import Data.Semigroup (Semigroup((<>)), )
 import Data.Tuple.HT (mapFst, fst3, snd3, thd3, mapFst3, mapThd3)
 
@@ -87,23 +91,25 @@
 import Data.Bool (Bool(False), not, (&&), (||))
 import Data.Eq (Eq, (==))
 import Data.Ord (Ord, Ordering(LT,GT), (<), (>))
-import Data.Tuple (uncurry)
+import Data.Tuple (snd, uncurry)
 import Data.Function (flip, (.), ($))
 import Data.Int (Int)
 import Text.Show
          (Show, ShowS, showParen, showString, showChar, shows, showsPrec)
 
-import Prelude (error)
+import Prelude (error, (+))
 
 
 {- $setup
 >>> import Test.Base
 >>>
+>>> import qualified Test.Data.Graph.Alternative as GraphAlt
 >>> import qualified Data.Graph.Comfort as Graph
 >>> import qualified Data.Map as Map
 >>> import qualified Data.Set as Set
 >>> import qualified Data.Char as Char
 >>> import Data.Graph.Comfort (Graph, DirEdge(DirEdge), UndirEdge(UndirEdge))
+>>> import Data.Tree (Forest)
 >>> import Data.Map (Map)
 >>> import Data.Tuple.HT (mapSnd)
 >>>
@@ -753,6 +759,29 @@
 
 
 {- |
+Edges point from the root to the leaves.
+-}
+fromTree :: Tree a -> Graph DirEdge Int () a
+fromTree = snd . flip MS.evalState 0 . fromTreeState
+
+fromForest :: Forest a -> Graph DirEdge Int () a
+fromForest =
+   Fold.foldMap snd . flip MS.evalState 0 . Trav.traverse fromTreeState
+
+fromTreeState :: Tree a -> MS.State Int (Int, Graph DirEdge Int () a)
+fromTreeState (Tree.Node root subTrees) = do
+   n <- MS.get
+   MS.put $ n+1
+   (subNodes, subTreeGraphs)
+      <- fmap List.unzip $ Trav.traverse fromTreeState subTrees
+   pure (n,
+      insertEdgeSet
+         (Map.fromList $ map (\subNode -> (DirEdge n subNode, ())) subNodes) $
+      insertNode n root $ mconcat subTreeGraphs)
+
+
+
+{- |
 prop> \(TestGraph gr) -> Graph.mapNode id gr === gr
 -}
 mapNode :: (nl0 -> nl1) -> Graph e n el nl0 -> Graph e n el nl1
@@ -875,6 +904,11 @@
       [(Graph.DirEdge 1 0, 23), (Graph.DirEdge 0 (1::Int), 42::Integer)]
 :}
 [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = []}]}]
+
+prop> :{
+   \(TestGraph gr) ->
+   Graph.depthFirstSearch gr === GraphAlt.depthFirstSearch gr
+:}
 -}
 depthFirstSearch ::
    (Edge edge, Ord node) =>
@@ -992,6 +1026,34 @@
 ["agr","d","hp"]
 
 
+Compare against alternative implementation:
+
+prop> :{
+   \(TestGraph gr) ->
+
+   Set.fromList (Graph.stronglyConnectedComponentsNE gr)
+   ===
+   Set.fromList (GraphAlt.stronglyConnectedComponents gr)
+:}
+
+
+Forests have no strongly connected components:
+
+prop> :{
+   \forest ->
+   let gr = Graph.fromForest (forest :: Forest Char) in
+   all (\comp -> Set.size comp == 1) $ Graph.stronglyConnectedComponents gr
+:}
+
+prop> :{
+   \forest -> let gr = Graph.fromForest (forest :: Forest Char) in
+   QC.forAll (genShuffledGraph gr) $ \(shuffled, _nodeMap) ->
+
+   all (\comp -> Set.size comp == 1) $
+   Graph.stronglyConnectedComponents shuffled
+:}
+
+
 Strongly connected components are invariant under reordering of nodes:
 
 prop> :{
@@ -1017,18 +1079,19 @@
 -}
 stronglyConnectedComponents ::
    (Ord node) => Graph DirEdge node edgeLabel nodeLabel -> [Set node]
-stronglyConnectedComponents gr =
-   let forest = depthFirstSearch gr
-       queue = List.foldl (flip buildReverseQueue) [] forest
+stronglyConnectedComponents =
+   map NonEmptySet.flatten . stronglyConnectedComponentsNE
+
+stronglyConnectedComponentsNE ::
+   (Ord node) => Graph DirEdge node edgeLabel nodeLabel -> [NonEmptySet.T node]
+stronglyConnectedComponentsNE gr =
+   let queue = List.foldl (flip buildReverseQueue) [] $ depthFirstSearch gr
        assignComponent root n = do
          assigned <- MS.gets $ Map.member n
          when (not assigned) $ do
             MS.modify $ Map.insert n root
-            Fold.mapM_ (assignComponent root) $ predecessors gr n
-       transposeMap =
-         Map.elems . Map.foldl (Map.unionWith Set.union) Map.empty .
-         Map.mapWithKey (\n root -> Map.singleton root $ Set.singleton n)
-   in transposeMap $
+            Fold.traverse_ (assignComponent root) $ predecessors gr n
+   in Map.elems $ MapU.transpose $
       MS.execState (Fold.mapM_ (\n -> assignComponent n n) queue) Map.empty
 
 
diff --git a/src/Data/Graph/Comfort/Map.hs b/src/Data/Graph/Comfort/Map.hs
--- a/src/Data/Graph/Comfort/Map.hs
+++ b/src/Data/Graph/Comfort/Map.hs
@@ -1,5 +1,6 @@
 module Data.Graph.Comfort.Map where
 
+import qualified Data.NonEmpty.Set as NonEmptySet
 import qualified Data.Set as Set
 import qualified Data.Map as Map
 import Data.Set (Set)
@@ -100,3 +101,9 @@
 
 compose :: (Ord a, Ord b) => Map b c -> Map a b -> Map a c
 compose bc ab = Map.mapMaybe (P.flip Map.lookup bc) ab
+
+transpose :: (Ord k, Ord a) => Map k a -> Map a (NonEmptySet.T k)
+transpose =
+   Map.foldl (Map.unionWith NonEmptySet.union) Map.empty .
+   Map.mapWithKey
+      (\n root -> Map.singleton root $ NonEmptySet.singleton n)
diff --git a/test/Test/Data/Graph/Alternative.hs b/test/Test/Data/Graph/Alternative.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Data/Graph/Alternative.hs
@@ -0,0 +1,81 @@
+module Test.Data.Graph.Alternative where
+
+import qualified Data.Graph.Comfort as Graph
+import Data.Graph.Comfort (Graph)
+
+import qualified Control.Monad.Trans.State as MS
+import Control.Monad (when)
+import Control.Applicative (liftA2)
+
+import qualified Data.NonEmpty.Set as NonEmptySet
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import qualified Data.Tree as Tree
+import qualified Data.Traversable as Trav
+import qualified Data.Foldable as Fold
+import Data.Map (Map)
+import Data.Set (Set)
+import Data.Tree (Tree, Forest)
+import Data.Maybe (catMaybes)
+import Data.Tuple.HT (mapFst, mapSnd)
+
+
+
+depthFirstSearch ::
+   (Graph.Edge edge, Ord node) =>
+   Graph edge node edgeLabel nodeLabel -> Forest node
+depthFirstSearch gr =
+   let go = do
+         unvisited <- MS.get
+         case Set.toAscList unvisited of
+            n:_ -> liftA2 (:) (depthFirstSearchFrom gr n) go
+            [] -> pure []
+   in MS.evalState go $ Graph.nodeSet gr
+
+depthFirstSearchFrom ::
+   (Graph.Edge edge, Ord node) =>
+   Graph edge node edgeLabel nodeLabel ->
+   node -> MS.State (Set node) (Tree node)
+depthFirstSearchFrom gr n = do
+   MS.modify $ Set.delete n
+   fmap (Tree.Node n . catMaybes) $
+      Trav.for (Graph.successors gr n) $ \suc -> do
+         unvisited <- MS.gets $ Set.member suc
+         if unvisited
+            then fmap Just $ depthFirstSearchFrom gr suc
+            else pure Nothing
+
+
+
+transposeMap :: (Ord k, Ord a) => Map k a -> Map a (NonEmptySet.T k)
+transposeMap =
+   Map.foldl (Map.unionWith NonEmptySet.union) Map.empty .
+   Map.mapWithKey
+      (\n root -> Map.singleton root $ NonEmptySet.singleton n)
+
+{-
+Direct imperative implementation of
+<https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm>
+-}
+stronglyConnectedComponents ::
+   (Ord node) =>
+   Graph Graph.DirEdge node edgeLabel nodeLabel -> [NonEmptySet.T node]
+stronglyConnectedComponents gr =
+   let visit u = do
+         unvisited <- MS.gets snd
+         when (Set.member u unvisited) $ do
+            MS.modify (mapSnd $ Set.delete u)
+            mapM_ visit $ Graph.successors gr u
+            MS.modify (mapFst (u :))
+       (queue, []) =
+         mapSnd Set.toList $
+         MS.execState
+            (mapM_ visit $ Graph.nodes gr)
+            ([], Graph.nodeSet gr)
+       assign root u = do
+         assignments <- MS.get
+         when (Map.notMember u assignments) $ do
+            MS.put $ Map.insert u root assignments
+            mapM_ (assign root) $ Graph.predecessors gr u
+   in Map.elems $ transposeMap $
+      MS.execState (Fold.mapM_ (\n -> assign n n) queue) Map.empty
diff --git a/test/Test/Data/Graph/Comfort.hs b/test/Test/Data/Graph/Comfort.hs
--- a/test/Test/Data/Graph/Comfort.hs
+++ b/test/Test/Data/Graph/Comfort.hs
@@ -1,19 +1,21 @@
 -- Do not edit! Automatically created with doctest-extract from src/Data/Graph/Comfort.hs
-{-# LINE 99 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 103 "src/Data/Graph/Comfort.hs" #-}
 
 module Test.Data.Graph.Comfort where
 
 import Test.DocTest.Base
 import qualified Test.DocTest.Driver as DocTest
 
-{-# LINE 100 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 104 "src/Data/Graph/Comfort.hs" #-}
 import     Test.Base
 
+import     qualified Test.Data.Graph.Alternative as GraphAlt
 import     qualified Data.Graph.Comfort as Graph
 import     qualified Data.Map as Map
 import     qualified Data.Set as Set
 import     qualified Data.Char as Char
 import     Data.Graph.Comfort (Graph, DirEdge(DirEdge), UndirEdge(UndirEdge))
+import     Data.Tree (Forest)
 import     Data.Map (Map)
 import     Data.Tuple.HT (mapSnd)
 
@@ -88,247 +90,286 @@
 
 test :: DocTest.T ()
 test = do
- DocTest.printPrefix "Data.Graph.Comfort:418: "
-{-# LINE 418 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:424: "
+{-# LINE 424 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 418 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 424 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) -> Graph.isConsistent (Graph.reverse gr)
   )
- DocTest.printPrefix "Data.Graph.Comfort:419: "
-{-# LINE 419 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:425: "
+{-# LINE 425 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 419 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 425 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) -> Graph.reverse (Graph.reverse gr) === gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:470: "
-{-# LINE 470 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:476: "
+{-# LINE 476 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 470 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 476 "src/Data/Graph/Comfort.hs" #-}
       Graph.isEmpty (Graph.empty :: MonoGraph)
   )
- DocTest.printPrefix "Data.Graph.Comfort:471: "
-{-# LINE 471 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:477: "
+{-# LINE 477 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 471 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 477 "src/Data/Graph/Comfort.hs" #-}
       Graph.isConsistent (Graph.empty :: MonoGraph)
   )
- DocTest.printPrefix "Data.Graph.Comfort:525: "
-{-# LINE 525 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:531: "
+{-# LINE 531 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 525 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 531 "src/Data/Graph/Comfort.hs" #-}
       \(GraphAndEdge gr e) -> Graph.lookupEdge e gr === Map.lookup e (Graph.edgeLabels gr)
   )
- DocTest.printPrefix "Data.Graph.Comfort:543: "
-{-# LINE 543 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:549: "
+{-# LINE 549 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 543 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 549 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) n -> Graph.lookupNode n gr === Map.lookup n (Graph.nodeLabels gr)
   )
- DocTest.printPrefix "Data.Graph.Comfort:594: "
-{-# LINE 594 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:600: "
+{-# LINE 600 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 594 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 600 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) n -> Graph.isConsistent $ deleteNodeIfExists n gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:595: "
-{-# LINE 595 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:601: "
+{-# LINE 601 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 595 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 601 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) n nl -> Graph.deleteNode n (Graph.insertNode n nl gr) === deleteNodeIfExists n gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:596: "
-{-# LINE 596 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:602: "
+{-# LINE 602 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 596 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 602 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) -> let isolatedNodes = filter (isolated gr) $ Graph.nodes gr in not (null isolatedNodes) ==> QC.forAll (QC.elements isolatedNodes) $ \n nl -> Graph.insertNode n nl gr === Graph.insertNode n nl (Graph.deleteNode n gr)
   )
- DocTest.printPrefix "Data.Graph.Comfort:622: "
-{-# LINE 622 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:628: "
+{-# LINE 628 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 622 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 628 "src/Data/Graph/Comfort.hs" #-}
       \(GraphAndEdge gr e) -> Graph.isConsistent $ Graph.deleteEdge e gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:623: "
-{-# LINE 623 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:629: "
+{-# LINE 629 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 623 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 629 "src/Data/Graph/Comfort.hs" #-}
       \(GraphAndEdge gr e) el -> Graph.deleteEdge e (Graph.insertEdge e el gr) === Graph.deleteEdge e gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:624: "
-{-# LINE 624 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:630: "
+{-# LINE 630 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 624 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 630 "src/Data/Graph/Comfort.hs" #-}
       \(GraphAndEdge gr e) el -> Graph.insertEdge e el gr === Graph.insertEdge e el (Graph.deleteEdge e gr)
   )
- DocTest.printPrefix "Data.Graph.Comfort:635: "
-{-# LINE 635 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:641: "
+{-# LINE 641 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 635 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 641 "src/Data/Graph/Comfort.hs" #-}
       \(GraphAndEdge gr e) -> Graph.filterEdgeWithKey (\ei _ -> e/=ei) gr === Graph.deleteEdge e gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:688: "
-{-# LINE 688 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:694: "
+{-# LINE 694 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 688 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 694 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) n nl -> Graph.isConsistent $ Graph.insertNode n nl gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:689: "
-{-# LINE 689 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:695: "
+{-# LINE 695 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 689 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 695 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) n nl -> Graph.lookupNode n (Graph.insertNode n nl gr) === Just nl
   )
- DocTest.printPrefix "Data.Graph.Comfort:701: "
-{-# LINE 701 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:707: "
+{-# LINE 707 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 701 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 707 "src/Data/Graph/Comfort.hs" #-}
       \(GraphAndEdge gr e) el -> Graph.isConsistent $ Graph.insertEdge e el gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:702: "
-{-# LINE 702 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:708: "
+{-# LINE 708 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 702 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 708 "src/Data/Graph/Comfort.hs" #-}
       \(GraphAndEdge gr e) el -> Graph.lookupEdge e (Graph.insertEdge e el gr) === Just el
   )
- DocTest.printPrefix "Data.Graph.Comfort:736: "
-{-# LINE 736 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:742: "
+{-# LINE 742 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 736 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 742 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) -> gr === Graph.fromMap (Graph.nodeLabels gr) (Graph.edgeLabels gr)
   )
- DocTest.printPrefix "Data.Graph.Comfort:756: "
-{-# LINE 756 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:785: "
+{-# LINE 785 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 756 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 785 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) -> Graph.mapNode id gr === gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:769: "
-{-# LINE 769 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:798: "
+{-# LINE 798 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 769 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 798 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) -> Graph.mapEdge id gr === gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:805: "
-{-# LINE 805 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:834: "
+{-# LINE 834 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 805 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 834 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) nl -> Graph.isConsistent $ evalTraverseNode nl gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:806: "
-{-# LINE 806 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:835: "
+{-# LINE 835 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 806 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 835 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) -> runIdentity (Graph.traverseNode (Identity . Char.toUpper) gr) === Graph.mapNode Char.toUpper gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:819: "
-{-# LINE 819 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:848: "
+{-# LINE 848 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 819 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 848 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) el -> Graph.isConsistent $ evalTraverseEdge el gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:820: "
-{-# LINE 820 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:849: "
+{-# LINE 849 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 820 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 849 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) el -> runIdentity (Graph.traverseEdge (Identity . (el+)) gr) === Graph.mapEdge (el+) gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:831: "
-{-# LINE 831 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:860: "
+{-# LINE 860 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 831 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 860 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) nl el -> Graph.isConsistent $ evalTraverse nl el gr
   )
- DocTest.printPrefix "Data.Graph.Comfort:832: "
-{-# LINE 832 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:861: "
+{-# LINE 861 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 832 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 861 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) nl el -> evalTraverse nl el gr === evalTraverseNode nl (evalTraverseEdge el gr)
   )
- DocTest.printPrefix "Data.Graph.Comfort:833: "
-{-# LINE 833 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:862: "
+{-# LINE 862 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 833 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 862 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) nl el -> evalTraverse nl el gr === evalTraverseEdge el (evalTraverseNode nl gr)
   )
- DocTest.printPrefix "Data.Graph.Comfort:834: "
-{-# LINE 834 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:863: "
+{-# LINE 863 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 834 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 863 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) nl -> flip MS.evalState nl (Graph.traverseNode nodeAction gr) === flip MS.evalState nl (Graph.traverse nodeAction pure gr)
   )
- DocTest.printPrefix "Data.Graph.Comfort:835: "
-{-# LINE 835 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:864: "
+{-# LINE 864 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 835 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 864 "src/Data/Graph/Comfort.hs" #-}
       \(TestGraph gr) el -> flip MS.evalState el (Graph.traverseEdge edgeAction gr) === flip MS.evalState el (Graph.traverse pure edgeAction gr)
   )
- DocTest.printPrefix "Data.Graph.Comfort:872: "
-{-# LINE 872 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:901: "
+{-# LINE 901 "src/Data/Graph/Comfort.hs" #-}
  DocTest.example(
-{-# LINE 872 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 901 "src/Data/Graph/Comfort.hs" #-}
       
    Graph.depthFirstSearch $
    Graph.fromList [(0,'A'),(1,'B')]
       [(Graph.DirEdge 1 0, 23), (Graph.DirEdge 0 (1::Int), 42::Integer)]
   )
   [ExpectedLine [LineChunk "[Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = []}]}]"]]
- DocTest.printPrefix "Data.Graph.Comfort:911: "
-{-# LINE 911 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:908: "
+{-# LINE 908 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.property(
+{-# LINE 908 "src/Data/Graph/Comfort.hs" #-}
+        
+   \(TestGraph gr) ->
+   Graph.depthFirstSearch gr === GraphAlt.depthFirstSearch gr
+  )
+ DocTest.printPrefix "Data.Graph.Comfort:945: "
+{-# LINE 945 "src/Data/Graph/Comfort.hs" #-}
  DocTest.example(
-{-# LINE 911 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 945 "src/Data/Graph/Comfort.hs" #-}
     mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['a'*->'a']
   )
   [ExpectedLine [LineChunk "(\"\",\"a\")"]]
- DocTest.printPrefix "Data.Graph.Comfort:913: "
-{-# LINE 913 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:947: "
+{-# LINE 947 "src/Data/Graph/Comfort.hs" #-}
  DocTest.example(
-{-# LINE 913 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 947 "src/Data/Graph/Comfort.hs" #-}
     mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['a'*->'h', 'a'*->'p', 'g'*->'r', 'p'*->'h', 'r'*->'a']
   )
   [ExpectedLine [LineChunk "(\"graph\",\"\")"]]
- DocTest.printPrefix "Data.Graph.Comfort:915: "
-{-# LINE 915 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:949: "
+{-# LINE 949 "src/Data/Graph/Comfort.hs" #-}
  DocTest.example(
-{-# LINE 915 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 949 "src/Data/Graph/Comfort.hs" #-}
     mapSnd Graph.nodes $ Graph.topologicalSort $ unlabGraph [] ['h'*->'a', 'a'*->'p', 'g'*->'r', 'p'*->'h', 'r'*->'a']
   )
   [ExpectedLine [LineChunk "(\"gr\",\"ahp\")"]]
- DocTest.printPrefix "Data.Graph.Comfort:938: "
-{-# LINE 938 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:972: "
+{-# LINE 972 "src/Data/Graph/Comfort.hs" #-}
  DocTest.example(
-{-# LINE 938 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 972 "src/Data/Graph/Comfort.hs" #-}
     map Graph.nodes $ Graph.components $ unlabGraph ['d'] ['a'*->'p', 'g'*->'r', 'p'*->'h']
   )
   [ExpectedLine [LineChunk "[\"ahp\",\"d\",\"gr\"]"]]
- DocTest.printPrefix "Data.Graph.Comfort:940: "
-{-# LINE 940 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:974: "
+{-# LINE 974 "src/Data/Graph/Comfort.hs" #-}
  DocTest.example(
-{-# LINE 940 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 974 "src/Data/Graph/Comfort.hs" #-}
     map Graph.nodes $ Graph.components $ unlabGraph ['d'] ['a'*-*'p', 'g'*-*'r', 'p'*-*'h']
   )
   [ExpectedLine [LineChunk "[\"ahp\",\"d\",\"gr\"]"]]
- DocTest.printPrefix "Data.Graph.Comfort:985: "
-{-# LINE 985 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:1019: "
+{-# LINE 1019 "src/Data/Graph/Comfort.hs" #-}
  DocTest.example(
-{-# LINE 985 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 1019 "src/Data/Graph/Comfort.hs" #-}
       
    Graph.stronglyConnectedComponents $
    Graph.fromList [(0,'A'),(1,'B')] [(Graph.DirEdge 0 (1::Int),42::Integer)]
   )
   [ExpectedLine [LineChunk "[fromList [0],fromList [1]]"]]
- DocTest.printPrefix "Data.Graph.Comfort:991: "
-{-# LINE 991 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:1025: "
+{-# LINE 1025 "src/Data/Graph/Comfort.hs" #-}
  DocTest.example(
-{-# LINE 991 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 1025 "src/Data/Graph/Comfort.hs" #-}
     map Set.toAscList $ Graph.stronglyConnectedComponents $ unlabGraph ['d'] ['g'*->'r', 'r'*->'a', 'a'*->'g', 'a'*->'p', 'p'*->'h', 'h'*->'p']
   )
   [ExpectedLine [LineChunk "[\"agr\",\"d\",\"hp\"]"]]
- DocTest.printPrefix "Data.Graph.Comfort:997: "
-{-# LINE 997 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:1031: "
+{-# LINE 1031 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 997 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 1031 "src/Data/Graph/Comfort.hs" #-}
         
    \(TestGraph gr) ->
+
+   Set.fromList (Graph.stronglyConnectedComponentsNE gr)
+   ===
+   Set.fromList (GraphAlt.stronglyConnectedComponents gr)
+  )
+ DocTest.printPrefix "Data.Graph.Comfort:1042: "
+{-# LINE 1042 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.property(
+{-# LINE 1042 "src/Data/Graph/Comfort.hs" #-}
+        
+   \forest ->
+   let gr = Graph.fromForest (forest :: Forest Char) in
+   all (\comp -> Set.size comp == 1) $ Graph.stronglyConnectedComponents gr
+  )
+ DocTest.printPrefix "Data.Graph.Comfort:1048: "
+{-# LINE 1048 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.property(
+{-# LINE 1048 "src/Data/Graph/Comfort.hs" #-}
+        
+   \forest -> let gr = Graph.fromForest (forest :: Forest Char) in
+   QC.forAll (genShuffledGraph gr) $ \(shuffled, _nodeMap) ->
+
+   all (\comp -> Set.size comp == 1) $
+   Graph.stronglyConnectedComponents shuffled
+  )
+ DocTest.printPrefix "Data.Graph.Comfort:1059: "
+{-# LINE 1059 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.property(
+{-# LINE 1059 "src/Data/Graph/Comfort.hs" #-}
+        
+   \(TestGraph gr) ->
    QC.forAll (genShuffledGraph gr) $ \(shuffled, nodeMap) ->
 
    Set.fromList
@@ -336,10 +377,10 @@
    ===
    Set.fromList (Graph.stronglyConnectedComponents shuffled)
   )
- DocTest.printPrefix "Data.Graph.Comfort:1011: "
-{-# LINE 1011 "src/Data/Graph/Comfort.hs" #-}
+ DocTest.printPrefix "Data.Graph.Comfort:1073: "
+{-# LINE 1073 "src/Data/Graph/Comfort.hs" #-}
  DocTest.property(
-{-# LINE 1011 "src/Data/Graph/Comfort.hs" #-}
+{-# LINE 1073 "src/Data/Graph/Comfort.hs" #-}
         
    \(TestGraph gr) ->
    Set.fromList (map Graph.nodeSet (Graph.components gr))
