1+ class MaxFlow {
2+ public class CapEdge {
3+ private final int from , to ;
4+ private long cap ;
5+ private final int rev ;
6+ CapEdge (int from , int to , long cap , int rev ) {
7+ this .from = from ;
8+ this .to = to ;
9+ this .cap = cap ;
10+ this .rev = rev ;
11+ }
12+ public int getFrom () {return from ;}
13+ public int getTo () {return to ;}
14+ public long getCap () {return cap ;}
15+ public long getFlow () {return g [to ][rev ].cap ;}
16+ }
17+
18+ private static final long INF = Long .MAX_VALUE ;
19+
20+ private final int n ;
21+ private int m ;
22+ private final java .util .ArrayList <CapEdge > edges ;
23+ private final int [] count ;
24+ private final CapEdge [][] g ;
25+
26+ public MaxFlow (int n ) {
27+ this .n = n ;
28+ this .edges = new java .util .ArrayList <>();
29+ this .count = new int [n ];
30+ this .g = new CapEdge [n ][];
31+ }
32+
33+ public int addEdge (int from , int to , long cap ) {
34+ vertexRangeCheck (from );
35+ vertexRangeCheck (to );
36+ capNonNegativeCheck (cap );
37+ CapEdge e = new CapEdge (from , to , cap , count [to ]);
38+ count [from ]++; count [to ]++;
39+ edges .add (e );
40+ return m ++;
41+ }
42+
43+ public CapEdge getEdge (int i ) {
44+ edgeRangeCheck (i );
45+ return edges .get (i );
46+ }
47+
48+ public java .util .ArrayList <CapEdge > getEdges () {
49+ return edges ;
50+ }
51+
52+ public void changeEdge (int i , long newCap , long newFlow ) {
53+ edgeRangeCheck (i );
54+ capNonNegativeCheck (newCap );
55+ if (newFlow > newCap ) {
56+ throw new IllegalArgumentException (
57+ String .format ("Flow %d is greater than capacity %d." , newCap , newFlow )
58+ );
59+ }
60+ CapEdge e = edges .get (i );
61+ CapEdge er = g [e .to ][e .rev ];
62+ e .cap = newCap - newFlow ;
63+ er .cap = newFlow ;
64+ }
65+
66+ private void buildGraph () {
67+ for (int i = 0 ; i < n ; i ++) {
68+ g [i ] = new CapEdge [count [i ]];
69+ }
70+ int [] idx = new int [n ];
71+ for (CapEdge e : edges ) {
72+ g [e .to ][idx [e .to ]++] = new CapEdge (e .to , e .from , 0 , idx [e .from ]);
73+ g [e .from ][idx [e .from ]++] = e ;
74+ }
75+ }
76+
77+ public long maxFlow (int s , int t ) {
78+ return flow (s , t , INF );
79+ }
80+
81+ public long flow (int s , int t , long flowLimit ) {
82+ vertexRangeCheck (s );
83+ vertexRangeCheck (t );
84+ buildGraph ();
85+ long flow = 0 ;
86+ int [] level = new int [n ];
87+ int [] que = new int [n ];
88+ int [] iter = new int [n ];
89+ while (true ) {
90+ java .util .Arrays .fill (level , -1 );
91+ dinicBFS (s , t , level , que );
92+ if (level [t ] < 0 ) return flow ;
93+ java .util .Arrays .fill (iter , 0 );
94+ while (true ) {
95+ long d = dinicDFS (t , s , flowLimit - flow , iter , level );
96+ if (d <= 0 ) break ;
97+ flow += d ;
98+ }
99+ }
100+ }
101+
102+ private void dinicBFS (int s , int t , int [] level , int [] que ) {
103+ int hd = 0 , tl = 0 ;
104+ que [tl ++] = s ;
105+ level [s ] = 0 ;
106+ while (tl > hd ) {
107+ int u = que [hd ++];
108+ for (CapEdge e : g [u ]) {
109+ int v = e .to ;
110+ if (e .cap <= 0 || level [v ] >= 0 ) continue ;
111+ level [v ] = level [u ] + 1 ;
112+ if (v == t ) return ;
113+ que [tl ++] = v ;
114+ }
115+ }
116+ }
117+
118+ private long dinicDFS (int cur , int s , long f , int [] iter , int [] level ) {
119+ if (cur == s ) return f ;
120+ long res = 0 ;
121+ while (iter [cur ] < count [cur ]) {
122+ CapEdge er = g [cur ][iter [cur ]++];
123+ int u = er .to ;
124+ CapEdge e = g [u ][er .rev ];
125+ if (level [u ] >= level [cur ] || e .cap <= 0 ) continue ;
126+ long d = dinicDFS (u , s , Math .min (f - res , e .cap ), iter , level );
127+ if (d <= 0 ) continue ;
128+ e .cap -= d ;
129+ er .cap += d ;
130+ res += d ;
131+ if (res == f ) break ;
132+ }
133+ return res ;
134+ }
135+
136+ public long fordFulkersonMaxFlow (int s , int t ) {
137+ return fordFulkersonFlow (s , t , INF );
138+ }
139+
140+ public long fordFulkersonFlow (int s , int t , long flowLimit ) {
141+ vertexRangeCheck (s );
142+ vertexRangeCheck (t );
143+ buildGraph ();
144+ boolean [] used = new boolean [n ];
145+ long flow = 0 ;
146+ while (true ) {
147+ java .util .Arrays .fill (used , false );
148+ long f = fordFulkersonDFS (s , t , flowLimit - flow , used );
149+ if (f <= 0 ) return flow ;
150+ flow += f ;
151+ }
152+ }
153+
154+ private long fordFulkersonDFS (int cur , int t , long f , boolean [] used ) {
155+ if (cur == t ) return f ;
156+ used [cur ] = true ;
157+ for (CapEdge e : g [cur ]) {
158+ if (used [e .to ] || e .cap <= 0 ) continue ;
159+ long d = fordFulkersonDFS (e .to , t , Math .min (f , e .cap ), used );
160+ if (d <= 0 ) continue ;
161+ e .cap -= d ;
162+ g [e .to ][e .rev ].cap += d ;
163+ return d ;
164+ }
165+ return 0 ;
166+ }
167+
168+ public boolean [] minCut (int s ) {
169+ vertexRangeCheck (s );
170+ boolean [] reachable = new boolean [n ];
171+ int [] stack = new int [n ];
172+ int ptr = 0 ;
173+ stack [ptr ++] = s ;
174+ reachable [s ] = true ;
175+ while (ptr > 0 ) {
176+ int u = stack [--ptr ];
177+ for (CapEdge e : g [u ]) {
178+ int v = e .to ;
179+ if (reachable [v ] || e .cap <= 0 ) continue ;
180+ reachable [v ] = true ;
181+ stack [ptr ++] = v ;
182+ }
183+ }
184+ return reachable ;
185+ }
186+
187+ private void vertexRangeCheck (int i ) {
188+ if (i < 0 || i >= n ) {
189+ throw new IndexOutOfBoundsException (
190+ String .format ("Index %d out of bounds for length %d" , i , n )
191+ );
192+ }
193+ }
194+
195+ private void edgeRangeCheck (int i ) {
196+ if (i < 0 || i >= m ) {
197+ throw new IndexOutOfBoundsException (
198+ String .format ("Index %d out of bounds for length %d" , i , m )
199+ );
200+ }
201+ }
202+
203+ private void capNonNegativeCheck (long cap ) {
204+ if (cap < 0 ) {
205+ throw new IllegalArgumentException (
206+ String .format ("Capacity %d is negative." , cap )
207+ );
208+ }
209+ }
210+ }
0 commit comments