Cod sursa(job #2838319)

Utilizator FunnyStockyMihnea Andreescu FunnyStocky Data 23 ianuarie 2022 13:13:17
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.29 kb
#include <vector>
#include <cstdio>
#include <queue>

using namespace std;

struct MCMF {
  const long long INFLL = (long long)1e18;
  const int INFINT = (int)1e9;
  int n, s, d;

  struct Edge {
    int to, cap, cost;
  };

  vector<Edge> edges;
  vector<int> deg;
  vector<int> verts;
  vector<int> parrent;
  vector<long long> mincost;
  vector<long long> off;
  vector<vector<int>> g;

  MCMF(int n, int m, int s, int d) : n(n), s(s), d(d), deg(n, 0), g(n), mincost(n), parrent(n), off(n) {
    edges.reserve(m);
  }

  void add(int a, int b, int cap, int cost) {
    edges.push_back({ b, cap, cost });
    edges.push_back({ a, 0, -cost });
    verts.push_back(a);
    verts.push_back(b);
    deg[a]++;
    deg[b]++;
  }

  void belf() {
    queue<int> q;
    vector<bool> inq(n, 0);
    for (int i = 0; i < n; i++) mincost[i] = INFLL;
    q.push(s);
    inq[s] = 1;
    mincost[s] = 0;
    while (!q.empty()) {
      int a = q.front();
      inq[a] = 0;
      q.pop();
      for (auto& i : g[a]) {
        if (edges[i].cap) {
          int b = edges[i].to;
          long long value_b = mincost[a] + edges[i].cost;
          if (value_b < mincost[b]) {
            mincost[b] = value_b;
            if (!inq[b]) q.push(b);
            parrent[b] = i;
          }
        }
      }
    }
    for (int i = 0; i < n; i++) off[i] = mincost[i];
  }

  void dij() {
    priority_queue<pair<long long, int>> q;
    for (int i = 0; i < n; i++) mincost[i] = INFLL;
    q.push({ 0, s });
    mincost[s] = 0;
    while (!q.empty()) {
      pair<long long, int> it = q.top();
      q.pop();
      if (mincost[it.second] != -it.first) continue;
      int a = it.second;
      for (auto& i : g[a]) {
        if (edges[i].cap) {
          int b = edges[i].to;
          long long value_b = mincost[a] + (edges[i].cost + off[a] - off[b]);
          if (value_b < mincost[b]) {
            mincost[b] = value_b;
            q.push({ -mincost[b], b });
            parrent[b] = i;
          }
        }
      }
    }
    for (int i = 0; i < n; i++) mincost[i] = mincost[i] - off[s] + off[i], off[i] = mincost[i];
  }

  pair<long long, long long> get() {
    for (int i = 0; i < n; i++) g[i].reserve(deg[i]);
    for (int i = 0; i < (int)verts.size(); i++) g[verts[i]].push_back(i);

    long long flow = 0, bestcostforflow = 0;
    belf();
    while (1) {
      dij();
      if (mincost[d] >= INFLL) break;
      int mn = INFINT;
      long long sumcost = 0;
      vector<int> path;
      for (int i = d; i != s; i = edges[(parrent[i] ^ 1)].to) {
        path.push_back(parrent[i]);
        mn = min(mn, edges[parrent[i]].cap);
        sumcost += edges[parrent[i]].cost;
      }
      for (auto& i : path) {
        edges[i].cap -= mn;
        edges[i ^ 1].cap += mn;
      }
      flow += mn;
      bestcostforflow += (long long)mn * sumcost;
    }
    return { flow, bestcostforflow };
  }
};

int main() {
  freopen("fmcm.in", "r", stdin);
  freopen("fmcm.out", "w", stdout);

  int n, m, s, d;
  scanf("%d %d %d %d", &n, &m, &s, &d);
  s--;
  d--;
  MCMF flow(n, m, s, d);
  while (m--) {
    int x, y, a, b;
    scanf("%d %d %d %d", &x, &y, &a, &b);
    x--;
    y--;
    flow.add(x, y, a, b);
  }
  printf("%lld\n", flow.get().second);
}