blob: 9b02969370f3b613bbf43e4cb9646631932de214 [file] [log] [blame] [edit]
(* Implementation based on:
* Robert Tarjan
* "Depth-first search and linear graph algorithms"
* SIAM Journal on Computing, 1(2), 1972
*)
(* Graph Representation *)
type vert = int array
type graph = vert array
module Set = Set.Make(Int)
(* SCC *)
type vert_info =
{ mutable index : int;
mutable low : int;
mutable onstack : bool;
}
let sccs (graph : graph) : Set.t list =
let len = Array.length graph in
if len = 0 then [] else
let info = Array.init len (fun _ -> {index = -1; low = -1; onstack = false}) in
let stack = Array.make len (-1) in
let stack_top = ref 0 in
let index = ref 0 in
let sccs = ref [] in
let rec connect x =
stack.(!stack_top) <- x;
incr stack_top;
let v = info.(x) in
v.onstack <- true;
v.index <- !index;
v.low <- !index;
incr index;
visit v graph.(x);
if v.low = v.index then sccs := scc x Set.empty :: !sccs
and scc x ys =
decr stack_top;
let y = stack.(!stack_top) in
info.(y).onstack <- false;
let ys' = Set.add y ys in
if x = y then ys' else scc x ys'
and visit v vert =
let succs = vert in
for i = 0 to Array.length succs - 1 do
let x = succs.(i) in
let w = info.(x) in
if w.index = -1 then begin
connect x;
v.low <- min v.low w.low
end else if w.onstack then
v.low <- min v.low w.index
done
in
for x = 0 to len - 1 do
if info.(x).index = -1 then connect x
done;
List.rev !sccs