@@ -59,12 +59,6 @@ public class McfGraph<TCap, TCapOp, TCost, TCostOp, TCast>
59
59
public McfGraph ( int n )
60
60
{
61
61
_n = n ;
62
- _g = new List < EdgeInternal > [ n ] ;
63
- for ( int i = 0 ; i < n ; i ++ )
64
- {
65
- _g [ i ] = new List < EdgeInternal > ( ) ;
66
- }
67
- _pos = new List < ( int first , int second ) > ( ) ;
68
62
}
69
63
70
64
/// <summary>
@@ -90,16 +84,8 @@ public int AddEdge(int from, int to, TCap cap, TCost cost)
90
84
DebugUtil . Assert ( 0 <= to && to < _n ) ;
91
85
DebugUtil . Assert ( capOp . LessThanOrEqual ( default , cap ) ) ;
92
86
DebugUtil . Assert ( costOp . LessThanOrEqual ( default , cost ) ) ;
93
- int m = _pos . Count ;
94
- _pos . Add ( ( from , _g [ from ] . Count ) ) ;
95
-
96
- int fromId = _g [ from ] . Count ;
97
- int toId = _g [ to ] . Count ;
98
-
99
- if ( from == to ) toId ++ ;
100
-
101
- _g [ from ] . Add ( new EdgeInternal ( to , toId , cap , cost ) ) ;
102
- _g [ to ] . Add ( new EdgeInternal ( from , fromId , default , costOp . Minus ( cost ) ) ) ;
87
+ int m = _edges . Count ;
88
+ _edges . Add ( new Edge ( from , to , cap , default , cost ) ) ;
103
89
return m ;
104
90
}
105
91
@@ -113,11 +99,9 @@ public int AddEdge(int from, int to, TCap cap, TCost cost)
113
99
/// </remarks>
114
100
public Edge GetEdge ( int i )
115
101
{
116
- int m = _pos . Count ;
102
+ int m = _edges . Count ;
117
103
DebugUtil . Assert ( 0 <= i && i < m ) ;
118
- var _e = _g [ _pos [ i ] . first ] [ _pos [ i ] . second ] ;
119
- var _re = _g [ _e . To ] [ _e . Rev ] ;
120
- return new Edge ( _pos [ i ] . first , _e . To , capOp . Add ( _e . Cap , _re . Cap ) , _re . Cap , _e . Cost ) ;
104
+ return _edges [ i ] ;
121
105
}
122
106
123
107
/// <summary>
@@ -127,16 +111,7 @@ public Edge GetEdge(int i)
127
111
/// <para>辺の順番はadd_edgeで追加された順番と同一。</para>
128
112
/// <para>計算量: m を追加された辺数として O(m)</para>
129
113
/// </remarks>
130
- public List < Edge > Edges ( )
131
- {
132
- int m = _pos . Count ;
133
- var result = new List < Edge > ( ) ;
134
- for ( int i = 0 ; i < m ; i ++ )
135
- {
136
- result . Add ( GetEdge ( i ) ) ;
137
- }
138
- return result ;
139
- }
114
+ public IReadOnlyList < Edge > Edges ( ) => _edges ;
140
115
141
116
/// <summary>
142
117
/// 頂点 <paramref name="s"/> から <paramref name="t"/> へ流せる限り流し、
@@ -271,51 +246,105 @@ public List<Edge> Edges()
271
246
DebugUtil . Assert ( 0 <= s && s < _n ) ;
272
247
DebugUtil . Assert ( 0 <= t && t < _n ) ;
273
248
DebugUtil . Assert ( s != t ) ;
249
+
250
+
251
+ int m = _edges . Count ;
252
+ var edgeIdx = new int [ m ] ;
253
+
254
+ CSR < EdgeInternal > g ;
255
+ {
256
+ var degree = new int [ _n ] ;
257
+ var redgeIdx = new int [ m ] ;
258
+ var elist = new List < ( int from , EdgeInternal edge ) > ( 2 * m ) ;
259
+
260
+ for ( int i = 0 ; i < m ; i ++ )
261
+ {
262
+ var e = _edges [ i ] ;
263
+ edgeIdx [ i ] = degree [ e . From ] ++ ;
264
+ redgeIdx [ i ] = degree [ e . To ] ++ ;
265
+ elist . Add ( ( e . From , new EdgeInternal ( e . To , - 1 , capOp . Subtract ( e . Cap , e . Flow ) , e . Cost ) ) ) ;
266
+ elist . Add ( ( e . To , new EdgeInternal ( e . From , - 1 , e . Flow , costOp . Minus ( e . Cost ) ) ) ) ;
267
+ }
268
+ g = new CSR < EdgeInternal > ( _n , elist ) ;
269
+ for ( int i = 0 ; i < m ; i ++ )
270
+ {
271
+ var e = _edges [ i ] ;
272
+ edgeIdx [ i ] += g . Start [ e . From ] ;
273
+ redgeIdx [ i ] += g . Start [ e . To ] ;
274
+ g . EList [ edgeIdx [ i ] ] . Rev = redgeIdx [ i ] ;
275
+ g . EList [ redgeIdx [ i ] ] . Rev = edgeIdx [ i ] ;
276
+ }
277
+ }
278
+
279
+ var result = Slope ( g , s , t , flowLimit ) ;
280
+
281
+ for ( int i = 0 ; i < m ; i ++ )
282
+ {
283
+ var e = g . EList [ edgeIdx [ i ] ] ;
284
+ _edges [ i ] . Flow = capOp . Subtract ( _edges [ i ] . Cap , e . Cap ) ;
285
+ }
286
+
287
+ return result ;
288
+ }
289
+
290
+
291
+ private List < ( TCap cap , TCost cost ) > Slope ( CSR < EdgeInternal > g , int s , int t , TCap flowLimit )
292
+ {
274
293
// variants (C = maxcost):
275
294
// -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0
276
- // reduced cost (= e.cost + dual[e.from] - dual[e.to ]) >= 0 for all edge
295
+ // reduced cost (= e.cost + dual[e.from] - dual[e.To ]) >= 0 for all edge
277
296
var dual = new TCost [ _n ] ;
278
297
var dist = new TCost [ _n ] ;
279
- var pv = new int [ _n ] ;
280
- var pe = new int [ _n ] ;
281
- var vis = new bool [ _n ] ;
298
+ var prevE = new int [ _n ] ;
299
+
282
300
283
301
bool DualRef ( )
284
302
{
285
303
dist . AsSpan ( ) . Fill ( costOp . MaxValue ) ;
286
- pv . AsSpan ( ) . Fill ( - 1 ) ;
287
- pe . AsSpan ( ) . Fill ( - 1 ) ;
288
- vis . AsSpan ( ) . Fill ( false ) ;
304
+ var vis = new bool [ _n ] ;
289
305
306
+ var queMin = new Stack < int > ( ) ;
290
307
var que = new PriorityQueueForMcf ( ) ;
308
+
291
309
dist [ s ] = default ;
292
- que . Enqueue ( default , s ) ;
293
- while ( que . Count > 0 )
310
+ queMin . Push ( s ) ;
311
+ while ( queMin . Count > 0 || que . Count > 0 )
294
312
{
295
- int v = que . Dequeue ( ) . to ;
313
+ int v ;
314
+ if ( queMin . Count > 0 )
315
+ v = queMin . Pop ( ) ;
316
+ else
317
+ v = que . Dequeue ( ) . to ;
296
318
if ( vis [ v ] ) continue ;
297
319
vis [ v ] = true ;
298
320
if ( v == t ) break ;
299
321
// dist[v] = shortest(s, v) + dual[s] - dual[v]
300
322
// dist[v] >= 0 (all reduced cost are positive)
301
323
// dist[v] <= (n-1)C
302
- for ( int i = 0 ; i < _g [ v ] . Count ; i ++ )
324
+ var dualV = dual [ v ] ;
325
+ var distV = dist [ v ] ;
326
+
327
+ var gStartCur = g . Start [ v ] ;
328
+ var gStartNext = g . Start [ v + 1 ] ;
329
+ for ( int i = gStartCur ; i < gStartNext ; i ++ )
303
330
{
304
- var e = _g [ v ] [ i ] ;
305
- if ( vis [ e . To ] || capOp . Equals ( e . Cap , default ) ) continue ;
306
- // |-dual[e.to ] + dual[v]| <= (n-1)C
331
+ var e = g . EList [ i ] ;
332
+ if ( EqualityComparer < TCap > . Default . Equals ( e . Cap , default ) ) continue ;
333
+ // |-dual[e.To ] + dual[v]| <= (n-1)C
307
334
// cost <= C - -(n-1)C + 0 = nC
308
- TCost cost = costOp . Add ( costOp . Subtract ( e . Cost , dual [ e . To ] ) , dual [ v ] ) ;
309
- if ( costOp . GreaterThan ( costOp . Subtract ( dist [ e . To ] , dist [ v ] ) , cost ) )
335
+ var cost = costOp . Add ( costOp . Subtract ( e . Cost , dual [ e . To ] ) , dualV ) ;
336
+ if ( costOp . GreaterThan ( costOp . Subtract ( dist [ e . To ] , distV ) , cost ) )
310
337
{
311
- dist [ e . To ] = costOp . Add ( dist [ v ] , cost ) ;
312
- pv [ e . To ] = v ;
313
- pe [ e . To ] = i ;
314
- que . Enqueue ( dist [ e . To ] , e . To ) ;
338
+ var distTo = costOp . Add ( distV , cost ) ;
339
+ dist [ e . To ] = distTo ;
340
+ prevE [ e . To ] = e . Rev ;
341
+ if ( EqualityComparer < TCost > . Default . Equals ( distTo , distV ) )
342
+ queMin . Push ( e . To ) ;
343
+ else
344
+ que . Enqueue ( distTo , e . To ) ;
315
345
}
316
346
}
317
347
}
318
-
319
348
if ( ! vis [ t ] )
320
349
{
321
350
return false ;
@@ -325,42 +354,42 @@ bool DualRef()
325
354
{
326
355
if ( ! vis [ v ] ) continue ;
327
356
// dual[v] = dual[v] - dist[t] + dist[v]
328
- // = dual[v] - (shortest(s, t) + dual[s] - dual[t]) + (shortest(s, v) + dual[s] - dual[v])
329
- // = - shortest(s, t) + dual[t] + shortest(s, v)
330
- // = shortest(s, v) - shortest(s, t) >= 0 - (n-1)C
357
+ // = dual[v] - (shortest(s, t) + dual[s] - dual[t]) +
358
+ // (shortest(s, v) + dual[s] - dual[v]) = - shortest(s,
359
+ // t) + dual[t] + shortest(s, v) = shortest(s, v) -
360
+ // shortest(s, t) >= 0 - (n-1)C
331
361
dual [ v ] = costOp . Subtract ( dual [ v ] , costOp . Subtract ( dist [ t ] , dist [ v ] ) ) ;
332
362
}
333
-
334
363
return true ;
335
364
}
336
365
366
+
337
367
TCap flow = default ;
338
368
TCost cost = default ;
339
- TCost prevCostPerFlow = costOp . Decrement ( default ) ; //-1
340
- var result = new List < ( TCap cap , TCost cost ) >
341
- {
342
- ( flow , cost )
343
- } ;
369
+ TCost prevCostPerFlow = costOp . Decrement ( default ) ;
370
+ var result = new List < ( TCap cap , TCost cost ) > { ( flow , cost ) } ;
344
371
while ( capOp . LessThan ( flow , flowLimit ) )
345
372
{
346
373
if ( ! DualRef ( ) ) break ;
347
- TCap c = capOp . Subtract ( flowLimit , flow ) ;
348
- for ( int v = t ; v != s ; v = pv [ v ] )
374
+ var c = capOp . Subtract ( flowLimit , flow ) ;
375
+ for ( int v = t ; v != s ; v = g . EList [ prevE [ v ] ] . To )
349
376
{
350
- if ( capOp . LessThan ( _g [ pv [ v ] ] [ pe [ v ] ] . Cap , c ) )
377
+ var c2 = g . EList [ g . EList [ prevE [ v ] ] . Rev ] . Cap ;
378
+ if ( capOp . LessThan ( c2 , c ) )
351
379
{
352
- c = _g [ pv [ v ] ] [ pe [ v ] ] . Cap ;
380
+ c = c2 ;
353
381
}
354
382
}
355
- for ( int v = t ; v != s ; v = pv [ v ] )
383
+ for ( int v = t ; v != s ; v = g . EList [ prevE [ v ] ] . To )
356
384
{
357
- _g [ pv [ v ] ] [ pe [ v ] ] . Cap = capOp . Subtract ( _g [ pv [ v ] ] [ pe [ v ] ] . Cap , c ) ;
358
- _g [ v ] [ _g [ pv [ v ] ] [ pe [ v ] ] . Rev ] . Cap = capOp . Add ( _g [ v ] [ _g [ pv [ v ] ] [ pe [ v ] ] . Rev ] . Cap , c ) ;
385
+ var e = g . EList [ prevE [ v ] ] ;
386
+ e . Cap = capOp . Add ( e . Cap , c ) ;
387
+ g . EList [ e . Rev ] . Cap = capOp . Subtract ( g . EList [ e . Rev ] . Cap , c ) ;
359
388
}
360
- TCost d = costOp . Minus ( dual [ s ] ) ;
389
+ var d = costOp . Minus ( dual [ s ] ) ;
361
390
flow = capOp . Add ( flow , c ) ;
362
391
cost = costOp . Add ( cost , costOp . Multiply ( cast . Cast ( c ) , d ) ) ;
363
- if ( costOp . Equals ( prevCostPerFlow , d ) )
392
+ if ( EqualityComparer < TCost > . Default . Equals ( prevCostPerFlow , d ) )
364
393
{
365
394
result . RemoveAt ( result . Count - 1 ) ;
366
395
}
@@ -373,7 +402,7 @@ bool DualRef()
373
402
/// <summary>
374
403
/// フローを流すグラフの各辺に対応した情報を持ちます。
375
404
/// </summary>
376
- public struct Edge : IEquatable < Edge >
405
+ public class Edge : IEquatable < Edge >
377
406
{
378
407
/// <summary>フローが流出する頂点。</summary>
379
408
public int From { get ; set ; }
@@ -422,8 +451,7 @@ public EdgeInternal(int to, int rev, TCap cap, TCost cost)
422
451
} ;
423
452
424
453
private readonly int _n ;
425
- private readonly List < ( int first , int second ) > _pos ;
426
- private readonly List < EdgeInternal > [ ] _g ;
454
+ private readonly List < Edge > _edges = new List < Edge > ( ) ;
427
455
428
456
private class PriorityQueueForMcf
429
457
{
@@ -452,7 +480,7 @@ public void Enqueue(TCost cost, int to)
452
480
while ( c > 0 )
453
481
{
454
482
int p = ( c - 1 ) >> 1 ;
455
- if ( costOp . Compare ( cost , _heap [ p ] . cost ) < 0 )
483
+ if ( costOp . LessThan ( cost , _heap [ p ] . cost ) )
456
484
{
457
485
_heap [ c ] = _heap [ p ] ;
458
486
c = p ;
@@ -476,12 +504,12 @@ public void Enqueue(TCost cost, int to)
476
504
int c = ( p << 1 ) + 1 ;
477
505
while ( c < n )
478
506
{
479
- if ( c != n - 1 && costOp . Compare ( _heap [ c ] . cost , _heap [ c + 1 ] . cost ) > 0 )
507
+ if ( c != n - 1 && costOp . GreaterThan ( _heap [ c ] . cost , _heap [ c + 1 ] . cost ) )
480
508
{
481
509
++ c ;
482
510
}
483
511
484
- if ( costOp . Compare ( _heap [ c ] . cost , item . cost ) < 0 )
512
+ if ( costOp . LessThan ( _heap [ c ] . cost , item . cost ) )
485
513
{
486
514
_heap [ p ] = _heap [ c ] ;
487
515
p = c ;
0 commit comments