@@ -6,105 +6,113 @@ using namespace std;
6
6
7
7
/* Minimum-Cost, Maximum-Flow solver using Successive Shortest Paths with Dijkstra and SPFA-SLF.
8
8
* Requirements:
9
- * - No duplicate or antiparallel edges with different costs.
9
+ * - Duplicate or antiparallel edges with different costs are allowed .
10
10
* - No negative cycles.
11
- * Time Complexity: O(Ef lg V) average-case, O(VE + Ef lg V) worst-case.
11
+ * Time Complexity: O(Ef lg V) average-case, O(VE + Ef lg V) worst-case with negative costs .
12
12
*/
13
13
template <int V, class T =long long >
14
14
class mcmf {
15
- unordered_map<int , T> cap[V], cost[V];
15
+ /* making this static breaks compilation on -O0, but not on -O2; possible bug in GCC */
16
+ const T INF = numeric_limits<T>::max();
17
+
18
+ struct edge {
19
+ int t, rev;
20
+ T cap, cost, f;
21
+ };
22
+
23
+ vector<edge> adj[V];
16
24
T dist[V];
17
25
int pre[V];
18
- bool visited [V];
26
+ bool vis [V];
19
27
20
- void spfa (int s) {
21
- static list<int > q;
28
+ void spfa (int s) { /* only needed if there are negative costs */
29
+ list<int > q;
22
30
23
31
memset (pre, -1 , sizeof pre);
24
- memset (dist, 63 , sizeof dist );
25
- memset (visited, 0 , sizeof visited );
32
+ memset (vis, 0 , sizeof vis );
33
+ fill (dist, dist + V, INF );
26
34
27
35
dist[s] = 0 ;
28
36
q.push_back (s);
29
37
while (!q.empty ()) {
30
38
int v = q.front ();
31
39
q.pop_front ();
32
- visited [v] = false ;
33
- for (auto p : cap [v]) if (p. second ) {
34
- int u = p. first ;
35
- T d = dist[v] + cost[v][u] ;
40
+ vis [v] = false ;
41
+ for (auto e : adj [v]) if (e. cap != e. f ) {
42
+ int u = e. t ;
43
+ T d = dist[v] + e. cost ;
36
44
if (d < dist[u]) {
37
- dist[u] = d, pre[u] = v ;
38
- if (!visited [u]) {
45
+ dist[u] = d, pre[u] = e. rev ;
46
+ if (!vis [u]) {
39
47
if (q.size () && d < dist[q.front ()]) q.push_front (u);
40
48
else q.push_back (u);
41
- visited [u] = true ;
49
+ vis [u] = true ;
42
50
}
43
51
}
44
52
}
45
53
}
46
54
}
47
55
48
- void dijkstra (int s) {
49
- static priority_queue<pair<T, int >, vector<pair<T, int > >,
50
- greater<pair<T, int > > > pq;
56
+ priority_queue<pair<T, int >, vector<pair<T, int > >,
57
+ greater<pair<T, int > > > pq; /* for dijkstra */
51
58
59
+ void dijkstra (int s) {
52
60
memset (pre, -1 , sizeof pre);
53
- memset (dist, 63 , sizeof dist );
54
- memset (visited, 0 , sizeof visited );
61
+ memset (vis, 0 , sizeof vis );
62
+ fill (dist, dist + V, INF );
55
63
56
64
dist[s] = 0 ;
57
- pq.push ({ 0 , s} );
65
+ pq.emplace ( 0 , s);
58
66
while (!pq.empty ()) {
59
67
int v = pq.top ().second ;
60
68
pq.pop ();
61
- if (visited [v]) continue ;
62
- visited [v] = true ;
63
- for (auto p : cap [v]) if (p. second ) {
64
- int u = p. first ;
65
- T d = dist[v] + cost[v][u] ;
69
+ if (vis [v]) continue ;
70
+ vis [v] = true ;
71
+ for (auto e : adj [v]) if (e. cap != e. f ) {
72
+ int u = e. t ;
73
+ T d = dist[v] + e. cost ;
66
74
if (d < dist[u]) {
67
- dist[u] = d, pre[u] = v ;
68
- pq.push ({ d, u} );
75
+ dist[u] = d, pre[u] = e. rev ;
76
+ pq.emplace ( d, u);
69
77
}
70
78
}
71
79
}
72
80
}
73
81
74
82
void reweight () {
75
- for (int v = 0 ; v < V; v++) {
76
- for (auto & p : cost[v]) {
77
- p.second += dist[v] - dist[p.first ];
78
- }
79
- }
83
+ for (int v = 0 ; v < V; v++)
84
+ for (auto & e : adj[v])
85
+ e.cost += dist[v] - dist[e.t ];
80
86
}
81
87
82
88
public:
83
89
unordered_map<int , T> flows[V];
84
90
85
- void add (int u, int v, T f=1 , T c=0 ) {
86
- cap[u][v] += f;
87
- cost[u][v] = c;
88
- cost[v][u] = -c;
91
+ void add (int u, int v, T cap=1 , T cost=0 ) {
92
+ adj[u].push_back ({ v, (int ) adj[v].size (), cap, cost, 0 });
93
+ adj[v].push_back ({ u, (int ) adj[u].size () - 1 , 0 , -cost, 0 });
89
94
}
90
95
91
96
pair<T, T> calc (int s, int t) {
92
- spfa (s);
97
+ spfa (s); /* comment out if all costs are non-negative */
93
98
T totalflow = 0 , totalcost = 0 ;
94
99
T fcost = dist[t];
95
100
while (true ) {
96
101
reweight ();
97
102
dijkstra (s);
98
103
if (~pre[t]) {
99
104
fcost += dist[t];
100
- T flow = cap[pre[t]][t];
101
- for (int v = t; ~pre[v]; v = pre[v])
102
- flow = min (flow, cap[pre[v]][v]);
103
- for (int v = t; ~pre[v]; v = pre[v]) {
104
- cap[pre[v]][v] -= flow;
105
- cap[v][pre[v]] += flow;
106
- flows[pre[v]][v] += flow;
107
- flows[v][pre[v]] -= flow;
105
+ T flow = INF;
106
+ for (int v = t; ~pre[v]; v = adj[v][pre[v]].t ) {
107
+ edge& r = adj[v][pre[v]];
108
+ edge& e = adj[r.t ][r.rev ];
109
+ flow = min (flow, e.cap - e.f );
110
+ }
111
+ for (int v = t; ~pre[v]; v = adj[v][pre[v]].t ) {
112
+ edge& r = adj[v][pre[v]];
113
+ edge& e = adj[r.t ][r.rev ];
114
+ e.f += flow;
115
+ r.f -= flow;
108
116
}
109
117
totalflow += flow;
110
118
totalcost += flow * fcost;
@@ -116,10 +124,8 @@ class mcmf {
116
124
117
125
void clear () {
118
126
for (int i = 0 ; i < V; i++) {
119
- cap[i].clear ();
120
- cost[i].clear ();
121
- flows[i].clear ();
122
- dist[i] = pre[i] = visited[i] = 0 ;
127
+ adj[i].clear ();
128
+ dist[i] = pre[i] = vis[i] = 0 ;
123
129
}
124
130
}
125
131
};
0 commit comments