Skip to content
Snippets Groups Projects
Commit 14f9db1d authored by Bruno Freitas Tissei's avatar Bruno Freitas Tissei
Browse files

Add Minimum Cost Maximum Flow

parent b328e501
No related branches found
No related tags found
No related merge requests found
...@@ -15,11 +15,11 @@ struct Dinic { ...@@ -15,11 +15,11 @@ struct Dinic {
Dinic(int N) : Dinic(int N) :
N(N), depth(N), start(N), graph(N) {} N(N), depth(N), start(N), graph(N) {}
void add_edge(int s, int t, int c) { void add_edge(int u, int v, int c) {
Edge forw = { t, 0, c, (int) graph[t].size() }; Edge forw = { v, 0, c, (int) graph[v].size() };
Edge back = { s, 0, 0, (int) graph[s].size() }; Edge back = { u, 0, 0, (int) graph[u].size() };
graph[s].pb(forw); graph[u].pb(forw);
graph[t].pb(back); graph[v].pb(back);
} }
bool bfs(int s, int t) { bool bfs(int s, int t) {
......
/// Minimum Cost Maximum Flow
///
/// Time: O(V^2 * E)
/// Space: O(V + E)
struct MinCostMaxFlow {
struct Edge { int u, v, cap, cost; };
int N;
vector<Edge> edges;
vector<vector<int>> adj;
vector<int> vis, dist, par, ind;
MinCostMaxFlow(int N) :
N(N), vis(N), dist(N), par(N), ind(N), adj(N) {}
void add_edge(int u, int v, int cap, int cost) {
adj[u].pb(edges.size());
edges.pb({ u, v, cap, cost });
adj[v].pb(edges.size());
edges.pb({ v, u, 0, -cost });
}
// Shortest Path Faster Algorithm (slower than
// Dijkstra but works with negative edges).
bool spfa(int s, int t) {
fill(all(dist), inf);
dist[s] = 0;
queue<int> Q;
Q.push(s);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
vis[u] = 0;
for (auto i : adj[u]) {
Edge &e = edges[i];
int v = e.v;
if (e.cap > 0 && dist[v] > dist[u] + e.cost) {
dist[v] = dist[u] + e.cost;
par[v] = u;
ind[v] = i;
if (!vis[v]) {
Q.push(v);
vis[v] = 1;
}
}
}
}
return dist[t] < inf;
}
// Returns pair (min_cost, max_flow).
ii run(int s, int t) {
int min_cost = 0;
int max_flow = 0;
while (spfa(s, t)) {
int flow = inf;
for (int i = t; i != s; i = par[i])
flow = min(flow, edges[ind[i]].cap);
for (int i = t; i != s; i = par[i]) {
edges[ind[i] ].cap -= flow;
edges[ind[i]^1].cap += flow;
}
min_cost += flow * dist[t];
max_flow += flow;
}
return ii(min_cost, max_flow);
}
};
No preview for this file type
#include <bits/stdc++.h> #include <bits/stdc++.h>
#define MAXN 110
#define MAXM 20010
#define EPS 1e-6 #define EPS 1e-6
#define MOD 1000000007 #define MOD 1000000007
#define inf 0x3f3f3f3f #define inf 0x3f3f3f3f
...@@ -16,63 +18,82 @@ ...@@ -16,63 +18,82 @@
using namespace std; using namespace std;
typedef long long ll; using ll = long long;
typedef pair<int,int> ii; using ii = pair<int,int>;
int N; struct MinCostMaxFlow {
int par[MAX]; struct Edge {
int graph[MAX][MAX], rg[MAX][MAX]; int u, v, cap, cost;
};
bool cont[MAX]; int N;
vector<Edge> edges;
vector<vector<int>> adj;
vector<int> vis, dist, par, ind;
MinCostMaxFlow(int N) :
N(N), vis(N), dist(N), par(N), ind(N), adj(N) {}
bool bfs(int s, int t) { void add_edge(int u, int v, int cap, int cost) {
queue<int> Q; adj[u].pb(edges.size());
Q.push(s); edges.pb({ u, v, cap, cost });
cont[s] = true;
while (!Q.empty()) { adj[v].pb(edges.size());
int u = Q.front(); Q.pop(); edges.pb({ v, u, 0, -cost });
// Sink was found, there is a path
if (u == t)
return true;
for (int i = 0; i < N; ++i)
if (!cont[i] && rg[u][i]) {
cont[i] = true;
par[i] = u;
Q.push(i);
}
} }
return false; bool spfa(int s, int t) {
} fill(all(dist), inf);
dist[s] = 0;
int edmonds_karp(int s, int t) { queue<int> Q;
int ans = 0; Q.push(s);
par[s] = -1;
mset(cont, 0); while (!Q.empty()) {
memcpy(rg, graph, sizeof(graph)); int u = Q.front(); Q.pop();
vis[u] = 0;
while (bfs(s, t)) { for (auto i : adj[u]) {
int flow = inf; Edge &e = edges[i];
int v = e.v;
for (int i = t; par[i] != -1; i = par[i]) if (e.cap > 0 && dist[v] > dist[u] + e.cost) {
flow = min(flow, rg[par[i]][i]); dist[v] = dist[u] + e.cost;
par[v] = u;
ind[v] = i;
for (int i = t; par[i] != -1; i = par[i]) { if (!vis[v]) {
rg[par[i]][i] -= flow; Q.push(v);
rg[i][par[i]] += flow; vis[v] = 1;
}
}
}
} }
ans += flow; return dist[t] < inf;
mset(cont, 0);
} }
return ans; pair<ll,int> run(int s, int t) {
} ll mincost = 0;
int maxflow = 0;
while (spfa(s, t)) {
ll flow = inf;
for (int i = t; i != s; i = par[i])
flow = min(flow, (ll) edges[ind[i]].cap);
for (int i = t; i != s; i = par[i]) {
edges[ind[i] ].cap -= flow;
edges[ind[i]^1].cap += flow;
}
mincost += flow * dist[t];
maxflow += flow;
}
return make_pair(mincost, maxflow);
}
};
int main() { int main() {
ios::sync_with_stdio(0); ios::sync_with_stdio(0);
...@@ -80,10 +101,23 @@ int main() { ...@@ -80,10 +101,23 @@ int main() {
int n, m; int n, m;
while (cin >> n >> m) { while (cin >> n >> m) {
MinCostMaxFlow mcmf(110);
vector<pair<ii,int>> aux(m);
for (int i = 0; i < m; ++i)
cin >> aux[i].fi.fi >> aux[i].fi.se >> aux[i].se;
int d, k; cin >> d >> k;
mcmf.add_edge(0, 1, d, 0);
for (int i = 0; i < m; ++i) { for (int i = 0; i < m; ++i) {
int a, b, c; cin >> a >> b >> c; mcmf.add_edge(aux[i].fi.fi, aux[i].fi.se, k, aux[i].se);
mcmf.add_edge(aux[i].fi.se, aux[i].fi.fi, k, aux[i].se);
} }
pair<ll,int> ans = mcmf.run(0, n);
if (ans.se != d) cout << "Impossible." << ende;
else cout << ans.fi << ende;
} }
return 0; return 0;
......
2
0 0 0 0 6 9 8 3 0
9 8 0 0 0 0 0 7 6
6 0 0 0 3 8 0 5 1
2 0 5 0 8 1 0 9 0
0 6 0 0 0 0 0 8 0
0 9 0 3 7 0 6 0 2
3 4 0 8 5 0 0 0 9
7 2 0 0 0 0 0 6 8
0 5 6 9 2 0 0 0 0
0 0 0 0 6 9 8 3 0
9 8 0 0 0 0 0 7 6
6 0 0 0 3 8 0 5 1
2 0 5 4 8 1 0 9 0
0 6 0 0 0 0 0 8 0
0 9 0 3 7 0 6 0 2
3 4 0 8 5 0 0 0 9
7 2 0 0 0 0 0 6 8
0 5 6 9 2 0 0 0 0
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment