max_flow.ml

Includes

type 't edge = { s : int; t : int; cap : 't ref; rev : 't ref }
type 't graph = 't edge list array

let add_edge ty g s t cap =
  let cap = ref cap in
  let rev = ref ty.zero in
  g.(s) <- { s = s; t = t; cap = cap; rev = rev } :: g.(s);
  g.(t) <- { s = t; t = s; cap = rev; rev = cap } :: g.(t)

let max_flow ty g s t =
  let v = Array.length g in
  let rec loop res =
    let d = Array.make v (-1) in
    let que = Queue.create () in
    d.(s) <- 0;
    Queue.push s que;
    while not (Queue.is_empty que) do
      let v = Queue.pop que in
      let update e =
        if !(e.cap) > ty.zero && d.(e.t) < 0
        then (d.(e.t) <- d.(v) + 1; Queue.push e.t que) in
      List.iter update g.(v)
    done;
    if d.(t) < 0
    then res
    else let iter = Array.copy g in
         let rec augument v f =
           if v = t
           then f
           else let rec iter_loop () =
                  ( match iter.(v) with
                    | [] -> ty.zero
                    | e :: new_iter ->
                       iter.(v) <- new_iter;
                       if !(e.cap) > ty.zero && d.(v) < d.(e.t)
                       then let ff = augument e.t (min f !(e.cap)) in
                            if ff > ty.zero
                            then ( e.cap := ty.sub !(e.cap) ff;
                                   e.rev := ty.add !(e.rev) ff;
                                   ff )
                            else iter_loop ()
                       else iter_loop () ) in
                iter_loop () in
         let rec loop_augument res =
           let f = augument s ty.inf in
           if f > ty.zero then loop_augument (ty.add res f) else res in
         loop (loop_augument res) in
  loop ty.zero

Back