-
Notifications
You must be signed in to change notification settings - Fork 20
/
ford-fulkerson.lisp
49 lines (47 loc) · 2.05 KB
/
ford-fulkerson.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
(defpackage :cp/ford-fulkerson
(:use :cl :cp/max-flow)
(:export #:max-flow!)
(:documentation
"Provides Ford-Fulkerson algorithm for maximum flow problem."))
(in-package :cp/ford-fulkerson)
(declaim (ftype (function * (values (integer 0 #.most-positive-fixnum) &optional))
%find-flow))
(defun %find-flow (graph src dest checked)
"DFS"
(declare (optimize (speed 3) (safety 0))
((mod #.array-dimension-limit) src dest)
(simple-bit-vector checked)
((simple-array list (*)) graph))
(fill checked 0)
(labels ((dfs (vertex flow)
(declare ((integer 0 #.most-positive-fixnum) flow))
(setf (aref checked vertex) 1)
(if (= vertex dest)
flow
(dolist (edge (aref graph vertex) 0)
(when (and (zerop (aref checked (edge-to edge)))
(> (edge-capacity edge) 0))
(let ((flow (dfs (edge-to edge) (min flow (edge-capacity edge)))))
(declare ((integer 0 #.most-positive-fixnum) flow))
(unless (zerop flow)
(decf (edge-capacity edge) flow)
(incf (edge-capacity (edge-reversed edge)) flow)
(return flow))))))))
(dfs src most-positive-fixnum)))
(declaim (ftype (function * (values (mod #.most-positive-fixnum) &optional))
max-flow!))
(defun max-flow! (graph src dest)
(declare (optimize (speed 3))
((mod #.array-dimension-limit) src dest)
((simple-array list (*)) graph))
(let ((checked (make-array (length graph) :element-type 'bit :initial-element 0))
(result 0))
(declare ((integer 0 #.most-positive-fixnum) result))
(loop
(let ((increment (%find-flow graph src dest checked)))
(cond ((zerop increment)
(return result))
((>= (+ result increment) most-positive-fixnum)
(error 'max-flow-overflow :graph graph))
(t
(incf result increment)))))))