1+ package com .jwetherell .algorithms .graph ;
2+
3+ import com .jwetherell .algorithms .data_structures .Graph ;
4+
5+ import java .util .ArrayList ;
6+ import java .util .Collection ;
7+ import java .util .LinkedList ;
8+ import java .util .Map ;
9+ import java .util .Queue ;
10+ import java .util .TreeMap ;
11+
12+ /**
13+ * @author mrowka
14+ */
15+ public class PushRelabel {
16+
17+ private static class Vertex {
18+ boolean visited = false ;
19+ int h ;
20+ int currentEdge ;
21+ long excess ;
22+ ArrayList <Edge > edges = new ArrayList <Edge >();
23+ }
24+
25+ private static class Edge {
26+ long c ;
27+ long f ;
28+ Vertex from ;
29+ Vertex to ;
30+ Edge revertedEdge ;
31+
32+ Edge (Vertex from , Vertex to , long c ) {
33+ this .from = from ;
34+ this .to = to ;
35+ this .c = c ;
36+
37+ }
38+
39+ Edge (Vertex from , Vertex to ) {
40+ this .from = from ;
41+ this .to = to ;
42+ }
43+
44+ @ Override
45+ public boolean equals (Object o ) {
46+ if (this == o ) {
47+ return true ;
48+ }
49+
50+ if (o == null || getClass () != o .getClass ()) {
51+ return false ;
52+ }
53+
54+ Edge edge = (Edge ) o ;
55+
56+ if (!from .equals (edge .from )) {
57+ return false ;
58+ }
59+ return to .equals (edge .to );
60+
61+ }
62+
63+ @ Override
64+ public int hashCode () {
65+ int result = from .hashCode ();
66+ result = 31 * result + to .hashCode ();
67+ return result ;
68+ }
69+ }
70+
71+ private Queue <Vertex > q = new LinkedList <Vertex >();
72+ private int relabelCounter ;
73+ private int n ;
74+ private ArrayList <Vertex > vertices = new ArrayList <Vertex >();
75+
76+ private Vertex s ;
77+ private Vertex t ;
78+
79+ private PushRelabel (Collection <Vertex > vertices , Vertex s , Vertex t ) {
80+ this .vertices .addAll (vertices );
81+ this .s = s ;
82+ this .t = t ;
83+ this .n = vertices .size ();
84+ }
85+
86+ /**
87+ * Computes maximum flow in flow network, using push-relabel algorithm with O(V^3) complexity.
88+ *
89+ * @param edgesToCapacities represents edges of network with capacities
90+ * @param source source of network
91+ * @param sink sink of network
92+ * @param <T> parameter of graph on which network is based
93+ * @return the maximum flow
94+ */
95+ public static <T extends Comparable <T >> Long getMaximumFlow (Map <Graph .Edge <T >, Long > edgesToCapacities , Graph .Vertex <T > source , Graph .Vertex <T > sink ) {
96+ if (edgesToCapacities == null ) {
97+ throw new IllegalArgumentException ("Graph is NULL." );
98+ }
99+
100+ Map <Graph .Vertex <T >, Vertex > vertexMap = new TreeMap <Graph .Vertex <T >, Vertex >();
101+
102+
103+ for (Graph .Edge <T > edge : edgesToCapacities .keySet ()) {
104+ vertexMap .put (edge .getFromVertex (), new Vertex ());
105+ vertexMap .put (edge .getToVertex (), new Vertex ());
106+ }
107+ Vertex s = new Vertex ();
108+ Vertex t = new Vertex ();
109+ vertexMap .put (source , s );
110+ vertexMap .put (sink , t );
111+
112+
113+ PushRelabel pushRelabel = new PushRelabel (vertexMap .values (), s , t );
114+
115+ for (Map .Entry <Graph .Edge <T >, Long > edgeWithCapacity : edgesToCapacities .entrySet ()) {
116+ pushRelabel .addEdge (
117+ vertexMap .get (edgeWithCapacity .getKey ().getFromVertex ()),
118+ vertexMap .get (edgeWithCapacity .getKey ().getToVertex ()),
119+ edgeWithCapacity .getValue ()
120+ );
121+ }
122+
123+ return pushRelabel .maxFlow ();
124+ }
125+
126+ private void addEdge (Vertex from , Vertex to , long c ) {
127+ int placeOfEdge = from .edges .indexOf (new Edge (from , to ));
128+ if (placeOfEdge == -1 ) {
129+ Edge edge = new Edge (from , to , c );
130+ Edge revertedEdge = new Edge (to , from , 0 );
131+ edge .revertedEdge = revertedEdge ;
132+ revertedEdge .revertedEdge = edge ;
133+ from .edges .add (edge );
134+ to .edges .add (revertedEdge );
135+ } else {
136+ from .edges .get (placeOfEdge ).c += c ;
137+ }
138+ }
139+
140+ private void recomputeHeigh () {
141+ Queue <Vertex > que = new LinkedList <Vertex >();
142+ for (Vertex vertex : vertices ) {
143+ vertex .visited = false ;
144+ vertex .h = 2 * n ;
145+ }
146+
147+ t .h = 0 ;
148+ s .h = n ;
149+ s .visited = true ;
150+ t .visited = true ;
151+ que .add (t );
152+ while (!que .isEmpty ()) {
153+ Vertex act = que .poll ();
154+ for (Edge e : act .edges ) {
155+ if (!e .to .visited && e .revertedEdge .c > e .revertedEdge .f ) {
156+ e .to .h = act .h + 1 ;
157+ que .add (e .to );
158+ e .to .visited = true ;
159+ }
160+ }
161+ }
162+ que .add (s );
163+ while (!que .isEmpty ()) {
164+ Vertex act = que .poll ();
165+ for (Edge e : act .edges ) {
166+ if (!e .to .visited && e .revertedEdge .c > e .revertedEdge .f ) {
167+ e .to .h = act .h + 1 ;
168+ que .add (e .to );
169+ e .to .visited = true ;
170+ }
171+ }
172+ }
173+ }
174+
175+ private void init () {
176+
177+ for (Edge e : s .edges ) {
178+ e .f = e .c ;
179+ e .revertedEdge .f = -e .f ;
180+ e .to .excess += e .f ;
181+ if (e .to != s && e .to != t ) {
182+ q .add (e .to );
183+ }
184+ }
185+ recomputeHeigh ();
186+ relabelCounter = 0 ;
187+ }
188+
189+ private void relabel (Vertex v ) {
190+ int minimum = 0 ;
191+ for (Edge e : v .edges ) {
192+ if (e .f < e .c ) {
193+ minimum = Math .min (minimum , e .to .h );
194+ }
195+ }
196+ v .h = minimum + 1 ;
197+ }
198+
199+ private void push (Vertex u , Edge e ) {
200+ long delta = (u .excess < e .c - e .f ) ? u .excess : e .c - e .f ;
201+ e .f += delta ;
202+ e .revertedEdge .f -= delta ;
203+ u .excess -= delta ;
204+ if (e .to .excess == 0 && e .to != s && e .to != t ) {
205+ q .add (e .to );
206+ }
207+ e .to .excess += delta ;
208+ }
209+
210+
211+ private void discharge (Vertex u ) {
212+ while (u .excess > 0 ) {
213+ if (u .currentEdge == u .edges .size ()) {
214+ relabel (u );
215+ if ((++relabelCounter ) == n ) {
216+ recomputeHeigh ();
217+ for (Vertex vertex : vertices ) {
218+ vertex .currentEdge = 0 ;
219+ }
220+ relabelCounter = 0 ;
221+ }
222+ u .currentEdge = 0 ;
223+ } else {
224+ Edge e = u .edges .get (u .currentEdge );
225+ if (e .f < e .c && u .h == e .to .h + 1 ) {
226+ push (u , e );
227+ } else u .currentEdge ++;
228+ }
229+ }
230+ }
231+
232+ private long maxFlow () {
233+ init ();
234+ while (!q .isEmpty ()) {
235+ discharge (q .poll ());
236+ }
237+ return t .excess ;
238+ }
239+
240+ }
0 commit comments