Cod sursa(job #3262761)

Utilizator LucaMuresanMuresan Luca Valentin LucaMuresan Data 11 decembrie 2024 16:00:39
Problema Flux maxim Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.27 kb
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
#include <queue>

#define debug(x) #x << " = " << x << '\n';

using ll = long long;
#define int ll
const int INF = 1e9;

struct Dinic {
  struct Edge {
    int to, flow, cap;
  };
  
  int n;
  std::vector<Edge> e;
  std::vector<std::vector<int>> g;
  std::vector<int> dist;
  int source, sink;

  Dinic() {}
  Dinic(int _n) {
    n = _n;
    g.resize(n + 1);
    dist.resize(n + 1);
  }

  void add_edge(int u, int v, int cap) {
    e.push_back({v, 0, cap});
    e.push_back({u, 0, 0});
    assert(1 <= u && u <= n);
    assert(1 <= v && v <= n);
    g[u].push_back((int) e.size() - 2);
    g[v].push_back((int) e.size() - 1);
  }

  bool can_bfs() {
    std::queue<int> q;
    dist.assign(n + 1, INF);
    q.push(source);
    dist[source] = 0;
    while (!q.empty()) {
      int u = q.front();
      q.pop();
      for (const auto &ind : g[u]) {
        auto &[v, flow, cap] = e[ind];
        if (flow < cap &&  dist[u] + 1 < dist[v]) {
          dist[v] = 1 + dist[u];
          q.push(v);
        }
      }
    }
    return dist[sink] != INF;
  }

  int do_push(int u, int F) {
    if (u == sink) {
      return F;
    }
    int pushed = 0;
    for (const auto &ind : g[u]) {
      auto &[v, flow, cap] = e[ind];
      if (dist[u] + 1 == dist[v] && flow < cap) {
        int push = do_push(v, std::min(F, cap - flow));
        pushed += push;
        flow += push;
        F -= push;
      }
    }
    return pushed;
  } 

  int max_flow(int _source, int _sink) {
    source = _source;
    sink = _sink;
    int answer = 0;
    while (can_bfs()) {
      int push = do_push(source, 1e9);
      answer += push;
      if (push == 0) {
        break;
      }
    }
    return answer;
  }
};

signed main() {
  #ifdef LOCAL
    freopen("input.txt", "r", stdin);
  #else
    freopen("maxflow.in", "r", stdin);
    freopen("maxflow.out", "w", stdout);
  #endif

  std::ios_base::sync_with_stdio(false);
  std::cin.tie(0);
  
  int n, m;
  std::cin >> n >> m;

  Dinic F(n + 1);

  for (int i = 0; i < m; i++) {
    int u, v, c;
    std::cin >> u >> v >> c;
    F.add_edge(u, v, c);
  }

  std::cout << F.max_flow(1, n);

  return 0;
}