Cod sursa(job #2912740)

Utilizator avtobusAvtobus avtobus Data 10 iulie 2022 14:25:33
Problema Flux maxim Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.39 kb
// 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;
}