Cod sursa(job #2981898)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 18 februarie 2023 22:58:32
Problema Flux maxim Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.7 kb
#include <cstdio>
#include <memory>
#include <vector>
#include <algorithm>
#include <queue>

using namespace std;

class Solver{
 private:
  void buildResidualGraph(const vector<tuple<int,int,int>> edges, int N) {
    Graph.resize(N);
    Capacity.resize(N, vector<int>(N));
    Flow.resize(N, vector<int>(N));
    Visited.resize(N);
    Parent.resize(N);
    for (auto [from, to, capacity]: edges) {
      Graph[from].emplace_back(to);
      Graph[to].emplace_back(from);
      Capacity[from][to] += capacity;
    }
  }
  bool BFS(int source, int sink) {
    queue<int> Q;
    fill(Visited.begin(), Visited.end(), false);
    int k = source;
    Q.emplace(k);
    Visited[k] = true;
    bool foundSomePath = false;
    while (!Q.empty()) {
      k = Q.front(); Q.pop();

      if (k == sink) {
	foundSomePath = true;
	continue;
      }
      
      for (auto v: Graph[k])
	if (!Visited[v] && Capacity[k][v] > Flow[k][v]) {
	  Visited[v] = true;
	  Q.emplace(v);
	  Parent[v] = k;
	}
    }
    return foundSomePath;
  }
  int maxFlow(const vector<tuple<int,int,int>>& edges, int N, int source, int sink) {
    int total = 0, crtFlow;
    buildResidualGraph(edges, N);
    while (BFS(source, sink))
      for (auto v: Graph[sink])
	if (Visited[v]) { // if v is a node that we found a path through
	  crtFlow = Capacity[v][sink] - Flow[v][sink];
	  for (int crtNode = v; crtNode != source && crtFlow; crtNode = Parent[crtNode])
	    crtFlow = min(crtFlow, Capacity[Parent[crtNode]][crtNode] - Flow[Parent[crtNode]][crtNode]);

	  if (!crtFlow)
	    continue;
	
	  for (int crtNode = v; crtNode != source; crtNode = Parent[crtNode]) {
	    Flow[Parent[crtNode]][crtNode] += crtFlow;
	    Flow[crtNode][Parent[crtNode]] -= crtFlow;
	  }
	  total += crtFlow;
	}
    return total;
  }
  vector<vector<int>> Graph; // Graph[i] = nodes adjacent to i
  vector<vector<int>> Capacity; // Capacity[i][j] = space from i to j
  vector<vector<int>> Flow; // Flow[i][j] = how much flows between i and j
  vector<int> Parent; // Parent[i] = previous node in the BFS on residual graph
  vector<bool> Visited; // Visited[i] = whether the node in the residual graph was visited during last BFS
 public:
  Solver() {
    freopen("maxflow.in", "r", stdin);
    freopen("maxflow.out", "w", stdout);
  }
  ~Solver() {
    fclose(stdin);
    fclose(stdout);
  }
  void execute() {
    int N, M;
    scanf("%d%d", &N, &M);
    vector<tuple<int,int,int>> edges;
    int from, to, capacity;
    for (int i = 0; i < M; ++i) {
      scanf("%d%d%d", &from, &to, &capacity);
      --from; --to;
      edges.emplace_back(from, to, capacity);
    }
    printf("%d\n", maxFlow(edges, N, 0, N - 1));
  }
};

int main() {
  unique_ptr<Solver> s = make_unique<Solver>();
  s->execute();
  return 0;
}