diff --git a/algorithms/graph/dinic.cpp b/algorithms/graph/dinic.cpp index 1403b4436df2d07a64b98e3730598bf8739467ee..fb65287d7ff7d164b87f978ee293830d9047dd3b 100644 --- a/algorithms/graph/dinic.cpp +++ b/algorithms/graph/dinic.cpp @@ -15,11 +15,11 @@ struct Dinic { Dinic(int N) : N(N), depth(N), start(N), graph(N) {} - void add_edge(int s, int t, int c) { - Edge forw = { t, 0, c, (int) graph[t].size() }; - Edge back = { s, 0, 0, (int) graph[s].size() }; - graph[s].pb(forw); - graph[t].pb(back); + void add_edge(int u, int v, int c) { + Edge forw = { v, 0, c, (int) graph[v].size() }; + Edge back = { u, 0, 0, (int) graph[u].size() }; + graph[u].pb(forw); + graph[v].pb(back); } bool bfs(int s, int t) { diff --git a/algorithms/graph/min_cost_max_flow.cpp b/algorithms/graph/min_cost_max_flow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff37950aedc271abe87842c3cfa663bb76371ef4 --- /dev/null +++ b/algorithms/graph/min_cost_max_flow.cpp @@ -0,0 +1,79 @@ +/// 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); + } +}; diff --git a/caderno.pdf b/caderno.pdf index 05adf703638921726f8fe8b69b23750388d1f202..3ae532569df79b62bfa711e4c399d821fab6ba0d 100644 Binary files a/caderno.pdf and b/caderno.pdf differ diff --git a/contests/Cadernaveis/UVA10594.cpp b/contests/Cadernaveis/UVA10594.cpp index 8a5b115e381cc538ffaf056ff7edee7eb68d4cd9..c0794ea984ade55b6a9fd3af58ad0232ada97027 100644 --- a/contests/Cadernaveis/UVA10594.cpp +++ b/contests/Cadernaveis/UVA10594.cpp @@ -1,5 +1,7 @@ #include <bits/stdc++.h> +#define MAXN 110 +#define MAXM 20010 #define EPS 1e-6 #define MOD 1000000007 #define inf 0x3f3f3f3f @@ -16,63 +18,82 @@ using namespace std; -typedef long long ll; -typedef pair<int,int> ii; +using ll = long long; +using ii = pair<int,int>; -int N; -int par[MAX]; -int graph[MAX][MAX], rg[MAX][MAX]; +struct MinCostMaxFlow { + struct Edge { + 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) { - queue<int> Q; - Q.push(s); - cont[s] = true; + void add_edge(int u, int v, int cap, int cost) { + adj[u].pb(edges.size()); + edges.pb({ u, v, cap, cost }); - while (!Q.empty()) { - int u = Q.front(); Q.pop(); - - // 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); - } + adj[v].pb(edges.size()); + edges.pb({ v, u, 0, -cost }); } - return false; -} + bool spfa(int s, int t) { + fill(all(dist), inf); + dist[s] = 0; -int edmonds_karp(int s, int t) { - int ans = 0; - par[s] = -1; + queue<int> Q; + Q.push(s); - mset(cont, 0); - memcpy(rg, graph, sizeof(graph)); + while (!Q.empty()) { + int u = Q.front(); Q.pop(); + vis[u] = 0; - while (bfs(s, t)) { - int flow = inf; + for (auto i : adj[u]) { + Edge &e = edges[i]; + int v = e.v; - for (int i = t; par[i] != -1; i = par[i]) - flow = min(flow, rg[par[i]][i]); + if (e.cap > 0 && dist[v] > dist[u] + e.cost) { + dist[v] = dist[u] + e.cost; + par[v] = u; + ind[v] = i; - for (int i = t; par[i] != -1; i = par[i]) { - rg[par[i]][i] -= flow; - rg[i][par[i]] += flow; + if (!vis[v]) { + Q.push(v); + vis[v] = 1; + } + } + } } - ans += flow; - mset(cont, 0); + return dist[t] < inf; } - 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() { ios::sync_with_stdio(0); @@ -80,10 +101,23 @@ int main() { int 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) { - 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; diff --git a/contests/Cadernaveis/in b/contests/Cadernaveis/in deleted file mode 100644 index 7fe77f6847af1c61e722fd515fb19ab9b3007682..0000000000000000000000000000000000000000 --- a/contests/Cadernaveis/in +++ /dev/null @@ -1,20 +0,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