Skip to content

Commit 3d8ffd0

Browse files
MCMF with dual
1 parent d23b2e2 commit 3d8ffd0

File tree

1 file changed

+302
-0
lines changed

1 file changed

+302
-0
lines changed

Max Flow/mcmf_with_dual.cpp

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
// CF Submission: https://codeforces.com/contest/1430/submission/95221926
2+
// #pragma GCC optimize("Ofast")
3+
// #pragma GCC target("avx2,bmi,bmi2,lzcnt")
4+
// #define NDEBUG
5+
6+
#include <bits/extc++.h>
7+
#include <x86intrin.h>
8+
9+
struct rep {
10+
struct iter {
11+
int i;
12+
constexpr void operator++() { ++i; }
13+
constexpr int operator*() const { return i; }
14+
friend constexpr bool operator!=(iter a, iter b) { return *a != *b; }
15+
};
16+
const int l, r;
17+
constexpr rep(int _l, int _r) : l(std::min(_l, _r)), r(_r) {}
18+
constexpr rep(int n) : rep(0, n) {}
19+
constexpr iter begin() const { return {l}; }
20+
constexpr iter end() const { return {r}; }
21+
};
22+
struct per {
23+
struct iter {
24+
int i;
25+
constexpr void operator++() { --i; }
26+
constexpr int operator*() const { return i; }
27+
friend constexpr bool operator!=(iter a, iter b) { return *a != *b; }
28+
};
29+
const int l, r;
30+
constexpr per(int _l, int _r) : l(std::min(_l, _r)), r(_r) {}
31+
constexpr per(int n) : per(0, n) {}
32+
constexpr iter begin() const { return {r - 1}; }
33+
constexpr iter end() const { return {l - 1}; }
34+
};
35+
template <class T, class U>
36+
constexpr bool chmin(T& a, U&& b) {
37+
return b < a ? a = std::forward<U>(b), true : false;
38+
}
39+
template <class T, class U>
40+
constexpr bool chmax(T& a, U&& b) {
41+
return a < b ? a = std::forward<U>(b), true : false;
42+
}
43+
44+
namespace atcoder {
45+
46+
template <class Cap, class Cost>
47+
struct mcf_graph {
48+
public:
49+
mcf_graph() {}
50+
mcf_graph(int n) : _n(n), g(n) {}
51+
52+
int add_edge(int from, int to, Cap cap, Cost cost) {
53+
assert(0 <= from && from < _n);
54+
assert(0 <= to && to < _n);
55+
int m = int(pos.size());
56+
pos.push_back({from, int(g[from].size())});
57+
int from_id = int(g[from].size());
58+
int to_id = int(g[to].size());
59+
if (from == to) to_id++;
60+
g[from].push_back(_edge{to, to_id, cap, cost});
61+
g[to].push_back(_edge{from, from_id, 0, -cost});
62+
return m;
63+
}
64+
65+
struct edge {
66+
int from, to;
67+
Cap cap, flow;
68+
Cost cost;
69+
};
70+
71+
edge get_edge(int i) {
72+
int m = int(pos.size());
73+
assert(0 <= i && i < m);
74+
auto _e = g[pos[i].first][pos[i].second];
75+
auto _re = g[_e.to][_e.rev];
76+
return edge{
77+
pos[i].first, _e.to, _e.cap + _re.cap, _re.cap, _e.cost,
78+
};
79+
}
80+
std::vector<edge> edges() {
81+
int m = int(pos.size());
82+
std::vector<edge> result(m);
83+
for (int i = 0; i < m; i++) {
84+
result[i] = get_edge(i);
85+
}
86+
return result;
87+
}
88+
89+
std::pair<Cap, Cost> flow(int s, int t) {
90+
return flow(s, t, std::numeric_limits<Cap>::max());
91+
}
92+
std::pair<Cap, Cost> flow(int s, int t, Cap flow_limit) {
93+
return slope(s, t, flow_limit).back();
94+
}
95+
std::vector<std::pair<Cap, Cost>> slope(int s, int t) {
96+
return slope(s, t, std::numeric_limits<Cap>::max());
97+
}
98+
std::vector<std::pair<Cap, Cost>> slope(int s, int t, Cap flow_limit) {
99+
assert(0 <= s && s < _n);
100+
assert(0 <= t && t < _n);
101+
assert(s != t);
102+
// variants (C = maxcost):
103+
// -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0
104+
// reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edge
105+
std::vector<Cost> dual(_n, 0), dist(_n);
106+
std::vector<int> pv(_n), pe(_n);
107+
std::vector<bool> vis(_n);
108+
auto dual_ref = [&]() {
109+
std::fill(dist.begin(), dist.end(), std::numeric_limits<Cost>::max());
110+
std::fill(pv.begin(), pv.end(), -1);
111+
std::fill(pe.begin(), pe.end(), -1);
112+
std::fill(vis.begin(), vis.end(), false);
113+
struct Q {
114+
Cost key;
115+
int to;
116+
bool operator<(Q r) const { return key > r.key; }
117+
};
118+
std::priority_queue<Q> que;
119+
dist[s] = 0;
120+
que.push(Q{0, s});
121+
while (!que.empty()) {
122+
int v = que.top().to;
123+
que.pop();
124+
if (vis[v]) continue;
125+
vis[v] = true;
126+
if (v == t) break;
127+
// dist[v] = shortest(s, v) + dual[s] - dual[v]
128+
// dist[v] >= 0 (all reduced cost are positive)
129+
// dist[v] <= (n-1)C
130+
for (int i = 0; i < int(g[v].size()); i++) {
131+
auto e = g[v][i];
132+
if (vis[e.to] || !e.cap) continue;
133+
// |-dual[e.to] + dual[v]| <= (n-1)C
134+
// cost <= C - -(n-1)C + 0 = nC
135+
Cost cost = e.cost - dual[e.to] + dual[v];
136+
if (dist[e.to] - dist[v] > cost) {
137+
dist[e.to] = dist[v] + cost;
138+
pv[e.to] = v;
139+
pe[e.to] = i;
140+
que.push(Q{dist[e.to], e.to});
141+
}
142+
}
143+
}
144+
if (!vis[t]) {
145+
return false;
146+
}
147+
148+
for (int v = 0; v < _n; v++) {
149+
if (!vis[v]) continue;
150+
// dual[v] = dual[v] - dist[t] + dist[v]
151+
// = dual[v] - (shortest(s, t) + dual[s] - dual[t]) +
152+
// (shortest(s, v) + dual[s] - dual[v]) = - shortest(s, t) +
153+
// dual[t] + shortest(s, v) = shortest(s, v) - shortest(s, t) >=
154+
// 0 - (n-1)C
155+
dual[v] -= dist[t] - dist[v];
156+
}
157+
return true;
158+
};
159+
Cap flow = 0;
160+
Cost cost = 0, prev_cost_per_flow = -1;
161+
std::vector<std::pair<Cap, Cost>> result;
162+
result.push_back({flow, cost});
163+
while (flow < flow_limit) {
164+
if (!dual_ref()) break;
165+
Cap c = flow_limit - flow;
166+
for (int v = t; v != s; v = pv[v]) {
167+
c = std::min(c, g[pv[v]][pe[v]].cap);
168+
}
169+
for (int v = t; v != s; v = pv[v]) {
170+
auto& e = g[pv[v]][pe[v]];
171+
e.cap -= c;
172+
g[v][e.rev].cap += c;
173+
}
174+
Cost d = -dual[s];
175+
flow += c;
176+
cost += c * d;
177+
if (prev_cost_per_flow == d) {
178+
result.pop_back();
179+
}
180+
result.push_back({flow, cost});
181+
prev_cost_per_flow = d;
182+
}
183+
return result;
184+
}
185+
186+
private:
187+
int _n;
188+
189+
struct _edge {
190+
int to, rev;
191+
Cap cap;
192+
Cost cost;
193+
};
194+
195+
std::vector<std::pair<int, int>> pos;
196+
std::vector<std::vector<_edge>> g;
197+
};
198+
199+
} // namespace atcoder
200+
201+
template <class Cap, class Cost>
202+
struct min_cost_b_flow {
203+
struct result {
204+
bool feasible;
205+
Cost cost;
206+
std::vector<Cap> flow;
207+
std::vector<Cost> dual;
208+
};
209+
210+
min_cost_b_flow() {}
211+
explicit min_cost_b_flow(int n) : g(n + 2), b(n) {}
212+
213+
int size() const { return std::size(b); }
214+
int add_edge(int src, int dst, Cap lower, Cap upper, Cost cost) {
215+
assert(0 <= src), assert(src < size());
216+
assert(0 <= dst), assert(dst < size());
217+
assert(lower <= upper);
218+
if (rev.push_back(cost < 0), rev.back()) {
219+
std::swap(src, dst);
220+
std::tie(lower, upper) = std::pair{-upper, -lower};
221+
cost = -cost;
222+
}
223+
b[src] -= lower;
224+
b[dst] += lower;
225+
res.cost += lower * cost;
226+
res.flow.push_back(lower);
227+
return g.add_edge(src, dst, upper - lower, cost);
228+
}
229+
void add_supply(int v, Cap x) {
230+
assert(0 <= v), assert(v < size());
231+
b[v] += x;
232+
}
233+
void add_demand(int v, Cap x) {
234+
assert(0 <= v), assert(v < size());
235+
b[v] -= x;
236+
}
237+
238+
result flow() {
239+
int source = size(), sink = source + 1;
240+
Cap positive{}, negative{};
241+
for (int v = 0; v < size(); ++v)
242+
if (b[v] > 0) {
243+
g.add_edge(source, v, b[v], 0);
244+
positive += b[v];
245+
} else if (b[v] < 0) {
246+
g.add_edge(v, sink, -b[v], 0);
247+
negative += -b[v];
248+
}
249+
if (positive != negative) return {};
250+
auto [flow, cost] = g.flow(source, sink);
251+
if (flow < positive) return {};
252+
res.feasible = true;
253+
res.cost += cost;
254+
std::vector<std::vector<std::pair<int, Cost>>> h(size());
255+
for (int i = 0; i < int(std::size(res.flow)); ++i) {
256+
auto e = g.get_edge(i);
257+
if (e.flow < e.cap) h[e.from].emplace_back(e.to, e.cost);
258+
if (e.flow > 0) h[e.to].emplace_back(e.from, -e.cost);
259+
res.flow[i] += e.flow;
260+
if (rev[i]) res.flow[i] = -res.flow[i];
261+
}
262+
res.dual.resize(size());
263+
std::vector<int> que(size());
264+
std::iota(begin(que), end(que), 0);
265+
std::vector in_que(size(), true);
266+
for (int bg = 0; bg < int(std::size(que));) {
267+
int v = que[bg++];
268+
in_que[v] = false;
269+
for (auto [u, c] : h[v]) {
270+
if (res.dual[v] + c < res.dual[u]) {
271+
res.dual[u] = res.dual[v] + c;
272+
if (not in_que[u]) in_que[u] = true, que.push_back(u);
273+
}
274+
}
275+
}
276+
return res;
277+
}
278+
279+
private:
280+
atcoder::mcf_graph<Cap, Cost> g;
281+
std::vector<Cap> b;
282+
std::vector<bool> rev;
283+
result res{};
284+
};
285+
286+
int main() {
287+
using namespace std;
288+
cin.tie(nullptr)->sync_with_stdio(false);
289+
int n, m;
290+
cin >> n >> m;
291+
min_cost_b_flow<int, int64_t> g(n);
292+
while (m--) {
293+
int x, y, w;
294+
cin >> x >> y >> w;
295+
--x, --y;
296+
g.add_edge(x, y, -1e7, w, 1);
297+
}
298+
auto ans = g.flow().dual;
299+
auto mx = *max_element(begin(ans), end(ans));
300+
for (auto&& e : ans) e = mx - e;
301+
for (int i : rep(n)) cout << ans[i] << " \n"[i == n - 1];
302+
}

0 commit comments

Comments
 (0)