Pagini recente » Istoria paginii runda/oni_cl_11-12_sim2 | Cod sursa (job #2173089) | Cod sursa (job #182491) | Istoria paginii runda/oni_cl_11-12_sim2 | Cod sursa (job #2912740)
// optimized Edmonds-Karp (precompute a BFS tree, reuse it multiple times)
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;
int main(void) {
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
freopen("maxflow.in", "r", stdin);
freopen("maxflow.out", "w", stdout);
int N, M;
cin >> N >> M;
int cnte = 0;
vector<int> head(N), nxt(2*M+1), to(2*M+1), from(2*M+1), cap(2*M+1,0), fl(2*M+1,0);
auto reve = [&M](int e){ return 2*M+1 - e; };
auto add_edge = [&](int u, int v, int cc){
++cnte;
nxt[cnte] = head[u];
head[u] = cnte;
to[cnte] = v;
from[cnte] = u;
cap[cnte] = cc;
int re = reve(cnte);
nxt[re] = head[v];
head[v] = re;
to[re] = u;
from[re] = v;
};
for(int i = 0; i < M; i++) {
int u,v,cc;
cin >> u >> v >> cc;
--u, --v;
add_edge(u, v, cc);
}
int src = 0, dest = N-1;
vector<bool> vis(N);
vector<int> par(N);
// builds the bfs tree
auto bfs_tree = [&]()->bool{
fill(vis.begin(), vis.end(), 0);
fill(par.begin(), par.end(), 0);
queue<int> Q;
Q.push(src); vis[src] = 1;
bool reachable = false;
while(!Q.empty()) {
int nod = Q.front(); Q.pop();
for(int e = head[nod]; e; e = nxt[e]) {
int nbr = to[e];
if (!vis[nbr] && fl[e] < cap[e]) {
if (nbr == dest) {
reachable = true;
} else {
par[nbr] = e;
vis[nbr] = 1;
Q.push(nbr);
}
}
}
}
return reachable;
};
int flow;
for(flow = 0; bfs_tree();) {
// this relies on the fact that only edges from dest are reverse edges;
for(int pre_dest_e = head[dest]; pre_dest_e; pre_dest_e = nxt[pre_dest_e]) {
int pre_dest_nod = to[pre_dest_e];
int re = reve(pre_dest_e);
int fmin = cap[re] - fl[re];
for(int nod = pre_dest_nod; nod != src && fmin > 0; nod = from[par[nod]]) {
int e = par[nod];
fmin = min(fmin, cap[e] - fl[e]);
}
if (fmin > 0) {
flow += fmin;
fl[pre_dest_e] += fmin;
fl[re] -= fmin;
for(int nod = pre_dest_nod; nod != src; nod = from[par[nod]]) {
int e = par[nod];
fl[e] += fmin;
fl[reve(e)] -= fmin;
}
}
}
}
cout << flow << "\n";
return 0;
}