let n = 8

let adj = [|
  [1];
  [2];
  [0; 3];
  [4];
  [5; 7];
  [6];
  [4];
  []
|]

let index_counter = ref 0
let stack = ref []
let on_stack = Array.make n false
let index_arr = Array.make n (-1)
let lowlink = Array.make n 0
let scc_count = ref 0

let rec strongconnect v =
  index_arr.(v) <- !index_counter;
  lowlink.(v) <- !index_counter;
  index_counter := !index_counter + 1;
  stack := v :: !stack;
  on_stack.(v) <- true;
  List.iter (fun w ->
    if index_arr.(w) = -1 then begin
      strongconnect w;
      if lowlink.(w) < lowlink.(v) then lowlink.(v) <- lowlink.(w)
    end else if on_stack.(w) then begin
      if index_arr.(w) < lowlink.(v) then lowlink.(v) <- index_arr.(w)
    end
  ) adj.(v);
  if lowlink.(v) = index_arr.(v) then begin
    let rec pop () =
      match !stack with
      | [] -> ()
      | w :: rest ->
        stack := rest;
        on_stack.(w) <- false;
        if w <> v then pop ()
    in
    pop ();
    scc_count := !scc_count + 1
  end

;;

for v = 0 to n - 1 do
  if index_arr.(v) = -1 then strongconnect v
done;
!scc_count
