Skip to content

Commit 91717c4

Browse files
committed
Update max flow code, fix MCMF
1 parent fe9c3e6 commit 91717c4

File tree

4 files changed

+61
-53
lines changed

4 files changed

+61
-53
lines changed

maxflow.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ using namespace std;
99
* - O(V^2 E) for general graphs, but in practice ~O(E^1.5)
1010
* - O(V^(1/2) E) for bipartite matching
1111
* - O(min(V^(2/3), E^(1/2)) E) for unit capacity graphs
12+
*
13+
* WARNING: prefer maxflow2.cpp when possible (which is faster)
1214
*/
1315
template<int V, class T=long long>
1416
class max_flow {

maxflow2.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ class max_flow {
5858

5959
public:
6060
void add(int u, int v, T cap=1, T rcap=0) {
61-
adj[u].push_back({ v, adj[v].size(), cap, 0 });
62-
adj[v].push_back({ u, adj[u].size() - 1, rcap, 0 });
61+
adj[u].push_back({ v, (int) adj[v].size(), cap, 0 });
62+
adj[v].push_back({ u, (int) adj[u].size() - 1, rcap, 0 });
6363
}
6464

6565
T calc(int s, int t) {

mincost_maxflow.cpp

Lines changed: 56 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,105 +6,113 @@ using namespace std;
66

77
/* Minimum-Cost, Maximum-Flow solver using Successive Shortest Paths with Dijkstra and SPFA-SLF.
88
* Requirements:
9-
* - No duplicate or antiparallel edges with different costs.
9+
* - Duplicate or antiparallel edges with different costs are allowed.
1010
* - 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.
1212
*/
1313
template<int V, class T=long long>
1414
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];
1624
T dist[V];
1725
int pre[V];
18-
bool visited[V];
26+
bool vis[V];
1927

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;
2230

2331
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);
2634

2735
dist[s] = 0;
2836
q.push_back(s);
2937
while (!q.empty()) {
3038
int v = q.front();
3139
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;
3644
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]) {
3947
if (q.size() && d < dist[q.front()]) q.push_front(u);
4048
else q.push_back(u);
41-
visited[u] = true;
49+
vis[u] = true;
4250
}
4351
}
4452
}
4553
}
4654
}
4755

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 */
5158

59+
void dijkstra(int s) {
5260
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);
5563

5664
dist[s] = 0;
57-
pq.push({0, s});
65+
pq.emplace(0, s);
5866
while (!pq.empty()) {
5967
int v = pq.top().second;
6068
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;
6674
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);
6977
}
7078
}
7179
}
7280
}
7381

7482
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];
8086
}
8187

8288
public:
8389
unordered_map<int, T> flows[V];
8490

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 });
8994
}
9095

9196
pair<T, T> calc(int s, int t) {
92-
spfa(s);
97+
spfa(s); /* comment out if all costs are non-negative */
9398
T totalflow = 0, totalcost = 0;
9499
T fcost = dist[t];
95100
while (true) {
96101
reweight();
97102
dijkstra(s);
98103
if (~pre[t]) {
99104
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;
108116
}
109117
totalflow += flow;
110118
totalcost += flow * fcost;
@@ -116,10 +124,8 @@ class mcmf {
116124

117125
void clear() {
118126
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;
123129
}
124130
}
125131
};

treap.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct tnode {
1515
int sz;
1616

1717
tnode() { update(); }
18-
18+
1919
void update() {
2020
sz = 1 + (l ? l->sz : 0) + (r ? r->sz : 0);
2121
}

0 commit comments

Comments
 (0)