Cod sursa(job #3325929)

Utilizator Radu_VasileRadu Vasile Radu_Vasile Data 26 noiembrie 2025 21:16:51
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.65 kb
#include <bits/stdc++.h>
const int INF = 1e9;
struct Flow{
  struct Edge{
    int u, cap, cost, rev_idx;
    Edge(int u, int cap, int cost, int rev_idx) : u(u), cap(cap), cost(cost), rev_idx(rev_idx){}
  };
  int n;
  std::vector<std::vector<Edge>> adj;
  std::vector<int> old_dist;

  std::vector<Edge*> prev;
  std::vector<Edge*> prev_rev;

  Flow(int n) : n(n), adj(n + 1), old_dist(n + 1), prev(n + 1), prev_rev(n + 1){};

  void add_edge(int u, int v, int cap, int cost) {
    adj[u].emplace_back(v, cap, cost, adj[v].size());
    adj[v].emplace_back(u, 0, -cost, adj[u].size() - 1);
  }

  void start_dist(int s) {
    std::queue<int> q;
    for( int i = 1; i <= n; i++ )
      old_dist[i] = INF;
    old_dist[s] = 0;
    q.push(s);
    while(!q.empty()) {
      int u = q.front();
      q.pop();
      for( auto &e : adj[u] ) {
        if(e.cap != 0 && old_dist[e.u] > old_dist[u] + 1) {
          old_dist[e.u] = old_dist[u] + 1;
          q.push(e.u);
        }
      }
    }
  }
  bool dijkstra(int s, int t) {
    std::vector<int> dist(n + 1, INF);
    std::priority_queue<std::pair<int, int>> pq;
    dist[s] = 0;
    pq.push({0, s});
    while(!pq.empty()) {
      auto [cost, u] = pq.top();
      pq.pop();

      if(-cost != dist[u])
        continue;
      for( auto &e : adj[u] ) {
        if(e.cap == 0)
          continue;
        int x = dist[u] + old_dist[u] - old_dist[e.u] + e.cost;
        if( x < dist[e.u] ) {
          dist[e.u] = x;
          pq.push({-dist[e.u], e.u});
          prev[e.u] = &e;
          prev_rev[e.u] = &adj[e.u][e.rev_idx];
        }
      }
    }

    for( int i = 1; i <= n; i++ )
      old_dist[i] += dist[i];
    return dist[t] < INF;
  }
  std::pair<int, int> flowcost(int s, int t) {
    start_dist(s);
    int flow = 0, cost = 0;
    while(dijkstra(s, t)) {
      int new_flow = INF, new_cost = 0;
      for( int a = t; a != s; a = prev_rev[a]->u ) {
        new_flow = std::min(new_flow, prev[a]->cap);
        new_cost += prev[a]->cost;
      }
      flow += new_flow;
      cost += new_cost * new_flow;
      for( int a = t; a != s; a = prev_rev[a]->u ) {
        prev_rev[a]->cap += new_flow;
        prev[a]->cap -= new_flow;
      }
    }
    return {flow, cost};
  }
};

int main() {
  std::ifstream fin("fmcm.in");
  std::ofstream fout("fmcm.out");

  int n, m, src, dest;
  fin >> n >> m >> src >> dest;

  Flow flow(n);
  for( int i = 0; i < m; i++ ){
    int a, b, cap, cost;
    fin >> a >> b >> cap >> cost;
    flow.add_edge( a, b, cap, cost );
  }

  auto [_, ret] = flow.flowcost( src, dest );

  fout << ret << "\n";
  return 0;
}