7
7
#include < queue>
8
8
#include < vector>
9
9
10
+ #include " atcoder/internal_csr"
11
+ #include " atcoder/internal_queue"
12
+
10
13
namespace atcoder {
11
14
12
15
template <class Cap , class Cost > struct mcf_graph {
13
16
public:
14
17
mcf_graph () {}
15
- mcf_graph (int n) : _n(n), g(n) {}
18
+ mcf_graph (int n) : _n(n) {}
16
19
17
20
int add_edge (int from, int to, Cap cap, Cost cost) {
18
21
assert (0 <= from && from < _n);
19
22
assert (0 <= to && to < _n);
20
23
assert (0 <= cap);
21
24
assert (0 <= cost);
22
- int m = int (pos.size ());
23
- pos.push_back ({from, int (g[from].size ())});
24
- int from_id = int (g[from].size ());
25
- int to_id = int (g[to].size ());
26
- if (from == to) to_id++;
27
- g[from].push_back (_edge{to, to_id, cap, cost});
28
- g[to].push_back (_edge{from, from_id, 0 , -cost});
25
+ int m = int (_edges.size ());
26
+ _edges.push_back ({from, to, cap, 0 , cost});
29
27
return m;
30
28
}
31
29
@@ -36,28 +34,17 @@ template <class Cap, class Cost> struct mcf_graph {
36
34
};
37
35
38
36
edge get_edge (int i) {
39
- int m = int (pos .size ());
37
+ int m = int (_edges .size ());
40
38
assert (0 <= i && i < m);
41
- auto _e = g[pos[i].first ][pos[i].second ];
42
- auto _re = g[_e.to ][_e.rev ];
43
- return edge{
44
- pos[i].first , _e.to , _e.cap + _re.cap , _re.cap , _e.cost ,
45
- };
46
- }
47
- std::vector<edge> edges () {
48
- int m = int (pos.size ());
49
- std::vector<edge> result (m);
50
- for (int i = 0 ; i < m; i++) {
51
- result[i] = get_edge (i);
52
- }
53
- return result;
39
+ return _edges[i];
54
40
}
41
+ std::vector<edge> edges () { return _edges; }
55
42
56
43
std::pair<Cap, Cost> flow (int s, int t) {
57
44
return flow (s, t, std::numeric_limits<Cap>::max ());
58
45
}
59
46
std::pair<Cap, Cost> flow (int s, int t, Cap flow_limit) {
60
- return slope (s, t, flow_limit).back ();
47
+ return slope (s, t, flow_limit).back ();
61
48
}
62
49
std::vector<std::pair<Cap, Cost>> slope (int s, int t) {
63
50
return slope (s, t, std::numeric_limits<Cap>::max ());
@@ -66,49 +53,122 @@ template <class Cap, class Cost> struct mcf_graph {
66
53
assert (0 <= s && s < _n);
67
54
assert (0 <= t && t < _n);
68
55
assert (s != t);
56
+
57
+ int m = int (_edges.size ());
58
+ std::vector<int > edge_idx (m);
59
+
60
+ auto g = [&]() {
61
+ std::vector<int > degree (_n), redge_idx (m);
62
+ std::vector<std::pair<int , _edge>> elist;
63
+ elist.reserve (2 * m);
64
+ for (int i = 0 ; i < m; i++) {
65
+ auto e = _edges[i];
66
+ edge_idx[i] = degree[e.from ]++;
67
+ redge_idx[i] = degree[e.to ]++;
68
+ elist.push_back ({e.from , {e.to , -1 , e.cap - e.flow , e.cost }});
69
+ elist.push_back ({e.to , {e.from , -1 , e.flow , -e.cost }});
70
+ }
71
+ auto _g = internal::csr<_edge>(_n, elist);
72
+ for (int i = 0 ; i < m; i++) {
73
+ auto e = _edges[i];
74
+ edge_idx[i] += _g.start [e.from ];
75
+ redge_idx[i] += _g.start [e.to ];
76
+ _g.elist [edge_idx[i]].rev = redge_idx[i];
77
+ _g.elist [redge_idx[i]].rev = edge_idx[i];
78
+ }
79
+ return _g;
80
+ }();
81
+
82
+ auto result = slope (g, s, t, flow_limit);
83
+
84
+ for (int i = 0 ; i < m; i++) {
85
+ auto e = g.elist [edge_idx[i]];
86
+ _edges[i].flow = _edges[i].cap - e.cap ;
87
+ }
88
+
89
+ return result;
90
+ }
91
+
92
+ private:
93
+ int _n;
94
+ std::vector<edge> _edges;
95
+
96
+ // inside edge
97
+ struct _edge {
98
+ int to, rev;
99
+ Cap cap;
100
+ Cost cost;
101
+ };
102
+
103
+ std::vector<std::pair<Cap, Cost>> slope (internal::csr<_edge>& g,
104
+ int s,
105
+ int t,
106
+ Cap flow_limit) {
69
107
// variants (C = maxcost):
70
108
// -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0
71
109
// reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edge
72
- std::vector<Cost> dual (_n, 0 ), dist (_n);
73
- std::vector<int > pv (_n), pe (_n);
110
+
111
+ // dual_dist[i] = (dual[i], dist[i])
112
+ std::vector<std::pair<Cost, Cost>> dual_dist (_n);
113
+ std::vector<int > prev_e (_n);
74
114
std::vector<bool > vis (_n);
75
115
struct Q {
76
116
Cost key;
77
117
int to;
78
118
bool operator <(Q r) const { return key > r.key ; }
79
119
};
120
+ std::vector<int > que_min;
80
121
std::vector<Q> que;
81
122
auto dual_ref = [&]() {
82
- std::fill (dist.begin (), dist.end (),
83
- std::numeric_limits<Cost>::max ());
123
+ for (int i = 0 ; i < _n; i++) {
124
+ dual_dist[i].second = std::numeric_limits<Cost>::max ();
125
+ }
84
126
std::fill (vis.begin (), vis.end (), false );
127
+ que_min.clear ();
85
128
que.clear ();
86
129
87
- dist[s] = 0 ;
88
- que.push_back (Q{0 , s});
89
- std::push_heap (que.begin (), que.end ());
90
- while (!que.empty ()) {
91
- int v = que.front ().to ;
92
- std::pop_heap (que.begin (), que.end ());
93
- que.pop_back ();
130
+ // que[0..heap_r) was heapified
131
+ size_t heap_r = 0 ;
132
+
133
+ dual_dist[s].second = 0 ;
134
+ que_min.push_back (s);
135
+ while (!que_min.empty () || !que.empty ()) {
136
+ int v;
137
+ if (!que_min.empty ()) {
138
+ v = que_min.back ();
139
+ que_min.pop_back ();
140
+ } else {
141
+ while (heap_r < que.size ()) {
142
+ heap_r++;
143
+ std::push_heap (que.begin (), que.begin () + heap_r);
144
+ }
145
+ v = que.front ().to ;
146
+ std::pop_heap (que.begin (), que.end ());
147
+ que.pop_back ();
148
+ heap_r--;
149
+ }
94
150
if (vis[v]) continue ;
95
151
vis[v] = true ;
96
152
if (v == t) break ;
97
153
// dist[v] = shortest(s, v) + dual[s] - dual[v]
98
154
// dist[v] >= 0 (all reduced cost are positive)
99
155
// dist[v] <= (n-1)C
100
- for (int i = 0 ; i < int (g[v].size ()); i++) {
101
- auto e = g[v][i];
102
- if (vis[e.to ] || !e.cap ) continue ;
156
+ Cost dual_v = dual_dist[v].first , dist_v = dual_dist[v].second ;
157
+ for (int i = g.start [v]; i < g.start [v + 1 ]; i++) {
158
+ auto e = g.elist [i];
159
+ if (!e.cap ) continue ;
103
160
// |-dual[e.to] + dual[v]| <= (n-1)C
104
161
// cost <= C - -(n-1)C + 0 = nC
105
- Cost cost = e.cost - dual[e.to ] + dual[v];
106
- if (dist[e.to ] - dist[v] > cost) {
107
- dist[e.to ] = dist[v] + cost;
108
- pv[e.to ] = v;
109
- pe[e.to ] = i;
110
- que.push_back (Q{dist[e.to ], e.to });
111
- std::push_heap (que.begin (), que.end ());
162
+ Cost cost = e.cost - dual_dist[e.to ].first + dual_v;
163
+ if (dual_dist[e.to ].second - dist_v > cost) {
164
+ Cost dist_to = dist_v + cost;
165
+ dual_dist[e.to ].second = dist_to;
166
+ prev_e[e.to ] = e.rev ;
167
+ if (dist_to == dist_v) {
168
+ que_min.push_back (e.to );
169
+ } else {
170
+ que.push_back (Q{dist_to, e.to });
171
+ }
112
172
}
113
173
}
114
174
}
@@ -119,29 +179,29 @@ template <class Cap, class Cost> struct mcf_graph {
119
179
for (int v = 0 ; v < _n; v++) {
120
180
if (!vis[v]) continue ;
121
181
// dual[v] = dual[v] - dist[t] + dist[v]
122
- // = dual[v] - (shortest(s, t) + dual[s] - dual[t]) + (shortest(s, v) + dual[s] - dual[v])
123
- // = - shortest(s, t) + dual[t] + shortest(s, v)
124
- // = shortest(s, v) - shortest(s, t) >= 0 - (n-1)C
125
- dual[v] -= dist[t] - dist[v];
182
+ // = dual[v] - (shortest(s, t) + dual[s] - dual[t]) +
183
+ // (shortest(s, v) + dual[s] - dual[v]) = - shortest(s,
184
+ // t) + dual[t] + shortest(s, v) = shortest(s, v) -
185
+ // shortest(s, t) >= 0 - (n-1)C
186
+ dual_dist[v].first -= dual_dist[t].second - dual_dist[v].second ;
126
187
}
127
188
return true ;
128
189
};
129
190
Cap flow = 0 ;
130
191
Cost cost = 0 , prev_cost_per_flow = -1 ;
131
- std::vector<std::pair<Cap, Cost>> result;
132
- result.push_back ({flow, cost});
192
+ std::vector<std::pair<Cap, Cost>> result = {{Cap (0 ), Cost (0 )}};
133
193
while (flow < flow_limit) {
134
194
if (!dual_ref ()) break ;
135
195
Cap c = flow_limit - flow;
136
- for (int v = t; v != s; v = pv[v] ) {
137
- c = std::min (c, g[pv[v]][pe[v] ].cap );
196
+ for (int v = t; v != s; v = g. elist [prev_e[v]]. to ) {
197
+ c = std::min (c, g. elist [g. elist [prev_e[v]]. rev ].cap );
138
198
}
139
- for (int v = t; v != s; v = pv[v] ) {
140
- auto & e = g[pv[v]][pe [v]];
141
- e.cap - = c;
142
- g[v][ e.rev ].cap + = c;
199
+ for (int v = t; v != s; v = g. elist [prev_e[v]]. to ) {
200
+ auto & e = g. elist [prev_e [v]];
201
+ e.cap + = c;
202
+ g. elist [ e.rev ].cap - = c;
143
203
}
144
- Cost d = -dual [s];
204
+ Cost d = -dual_dist [s]. first ;
145
205
flow += c;
146
206
cost += c * d;
147
207
if (prev_cost_per_flow == d) {
@@ -152,18 +212,6 @@ template <class Cap, class Cost> struct mcf_graph {
152
212
}
153
213
return result;
154
214
}
155
-
156
- private:
157
- int _n;
158
-
159
- struct _edge {
160
- int to, rev;
161
- Cap cap;
162
- Cost cost;
163
- };
164
-
165
- std::vector<std::pair<int , int >> pos;
166
- std::vector<std::vector<_edge>> g;
167
215
};
168
216
169
217
} // namespace atcoder
0 commit comments