@@ -621,87 +621,63 @@ class Graph<T> {
621621 return components ;
622622 } ;
623623
624- // dfs iterative
625- // Returns: a list of all verteces found (in the order of dequeue)
626- // the parent of each visited vertex
627- // all visited verteces
628- dfs = ( s : T ) => {
629- // popped stack order
630- const result : Array < T > = new Array ( ) ;
631- const parents : Map < T , null | T > = new Map ( ) ;
632- // a node is visited when it is popped from the stack
633- const visited : Map < T , boolean > = new Map ( ) ;
634- const stack = new Stack ( ) ;
635- stack . push ( s ) ;
636- parents . set ( s , null ) ;
637- let v : Node ;
638-
639- while ( stack . size !== 0 ) {
640- // take from the top of the stack
641- v = stack . pop ( ) ! ;
642- if ( ! visited . get ( v . key ) ) {
643- result . push ( v . key ) ;
644- visited . set ( v . key , true ) ;
645- }
646- this . list . get ( v . key ) ! . forEach ( ( u ) => {
647- if ( ! visited . get ( u . node ) ) {
648- parents . set ( u . node , v . key ) ;
649- stack . push ( u . node ) ;
650- }
651- } ) ;
652- }
653- return {
654- result,
655- parents,
656- visited,
657- } ;
658- } ;
659-
660624 // dfs recursive
661- // Returns: a list of all verteces found (in the order of dequeue)
662- // the parent of each visited vertex
663- // all visited verteces
664- dfsRec = (
625+ dfs = (
665626 s : T ,
666- visited : Map < T , boolean > = new Map ( ) ,
627+ // white: unvisited node (not used in this implementation)
628+ // first time we see a node it is not in the map
629+ // gray: visited node, but not finish (all neighbours also visited)
630+ // black: finished node
631+ color : Map < T , string > = new Map ( ) ,
667632 labeledOrder : Map < T , number | null > = new Map ( ) ,
668- finish : Array < T > = new Array ( )
633+ finish : Array < T > = new Array ( ) ,
634+ parents : Map < T , T > = new Map ( ) ,
635+ cycle = false
669636 ) => {
670637 // mark s as visited
671- visited . set ( s , true ) ;
638+ color . set ( s , "gray" ) ;
672639 // for every edge of s
673640 this . list . get ( s ) ! . forEach ( ( u ) => {
674- if ( ! visited . get ( u . node ) ) {
641+ if ( ! color . get ( u . node ) ) {
642+ // set u as a child of s
643+ parents . set ( u . node , s ) ;
675644 // recursive call
676- this . dfsRec ( u . node , visited , labeledOrder , finish ) ;
645+ this . dfs ( u . node , color , labeledOrder , finish , parents , cycle ) ;
646+ } else if ( color . get ( u . node ) === "gray" ) {
647+ // back edge:
648+ // u is an ancestor of s (i.e., there is some path u -> s, and now we found an edge s -> u)
649+ // forming a cycle
650+ cycle = true ;
677651 }
678652 } ) ;
679- if ( ! labeledOrder . get ( s ) ) {
680- labeledOrder . set ( s , this . currentLabel ) ;
681- this . currentLabel ! -- ;
682- finish . push ( s ) ;
683- }
653+ // all neighbours visited => finished!
654+ labeledOrder . set ( s , this . currentLabel ) ;
655+ color . set ( s , "black" ) ;
656+ this . currentLabel ! -- ;
657+ finish . push ( s ) ;
684658 return {
685659 labeledOrder,
686- visited ,
660+ color ,
687661 finish,
662+ parents,
663+ cycle,
688664 } ;
689665 } ;
690666
691667 // Returns the labeled order and finish order
692668 // Does not work for cycled graphs, only DAGs
693669 topologicalSort ( ) {
694670 const labeledOrder : Map < T , number | null > = new Map ( ) ;
695- const visited : Map < T , boolean > = new Map ( ) ;
671+ const color : Map < T , string > = new Map ( ) ;
696672 const finish : Array < T > = new Array ( ) ;
697673 // to keep track of ordering
698674 this . currentLabel = this . list . size ;
699675 for ( let [ u ] of this . list ) {
700- if ( ! visited . get ( u ) ) {
701- const r = this . dfsRec ( u ) ;
676+ if ( ! color . get ( u ) ) {
677+ const r = this . dfs ( u ) ;
702678 // update values
703- r . visited . forEach ( ( value , key ) => {
704- visited . set ( key , value ) ;
679+ r . color . forEach ( ( value , key ) => {
680+ color . set ( key , value ) ;
705681 } ) ;
706682 r . labeledOrder . forEach ( ( value , key ) => {
707683 labeledOrder . set ( key , value ) ;
@@ -720,20 +696,22 @@ class Graph<T> {
720696 // finish order
721697 if ( gRerv === false ) return false ;
722698 const { finish } = gRerv . topologicalSort ( ) ;
723- const visited : Map < T , boolean > = new Map ( ) ;
699+ const color : Map < T , string > = new Map ( ) ;
724700 // the vertex who calls dfs (maps leader's vertex key to the size of the Strong Component)
725701 const leader : Map < T , number > = new Map ( ) ;
726702 let u , r ;
727- for ( let i = 0 ; i < finish . length ; i ++ ) {
703+ // for (let i = 0; i < finish.length; i++) {
704+ for ( let i = finish . length - 1 ; i > 0 ; i -- ) {
728705 u = finish [ i ] ;
729- if ( ! visited . get ( u ) ) {
730- r = this . dfs ( u ) ;
706+ if ( ! color . get ( u ) ) {
707+ // r = this.dfs(u);
708+ r = this . dfs ( u , color ) ;
731709 // update visited
732- r . visited . forEach ( ( value , key ) => {
733- visited . set ( key , value ) ;
710+ r . color . forEach ( ( value , key ) => {
711+ color . set ( key , value ) ;
734712 } ) ;
735713 // all verteces visited have u as leader
736- leader . set ( u , r . result . length ) ;
714+ leader . set ( u , r . finish . length ) ;
737715 }
738716 }
739717 return leader ;
0 commit comments