Cod sursa(job #2691654)

Utilizator retrogradLucian Bicsi retrograd Data 29 decembrie 2020 15:35:23
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.61 kb
#include <bits/stdc++.h>

using namespace std;

using T = int;
const T INF = numeric_limits<T>::max() / 4;

struct MFMC {
  struct Edge { int from, to; T flow, cap, cost; };
  
  int n;
  vector<T> dist, pi;
  vector<int> par; vector<vector<int>> graph;
  vector<vector<T>> flow, cap, cost;
  vector<Edge> es;
  
  MFMC(int n) : n(n), pi(n, 0), par(n, -1), graph(n), flow(n, vector<T>(n, 0)), cap(flow), cost(flow) {}
  
  void AddEdge(int a, int b, T c, T k) {
    auto add = [&](int a, int b, T c, T k) {
      graph[a].push_back(b);
      cap[a][b] = c; cost[a][b] = k;
    };
    add(a, b, c, k); add(b, a, 0, -k);
  }
  bool relax(int node, int vec) {
    if (dist[node] == INF) return false;
    T now = dist[node] + pi[node] - pi[vec] + cost[node][vec];
    if (flow[node][vec] < cap[node][vec] && now < dist[vec]) {
      dist[vec] = now; par[vec] = node;
      return true;
    }
    return false;
  }
  bool dijkstra(int s, int t) {
    dist.assign(n, INF); par.assign(n, -1);
    priority_queue<pair<T, int>> pq; 
    dist[s] = 0; pq.emplace(0, s); 
    while (!pq.empty()) {
      T d; int node; tie(d, node) = pq.top(); pq.pop(); 
      // auto [d, node] = pq.top(); pq.pop();
      if (dist[node] != -d) continue;
      for (auto vec : graph[node]) 
        if (relax(node, vec)) 
          pq.emplace(-dist[vec], vec);
    }
    for (int i = 0; i < n; ++i) {
      assert(dist[i] >= 0);
      pi[i] = min(pi[i] + dist[i], INF);
    }
    return par[t] != -1;
  }
  pair<T, T> Compute(int s, int t) {
    T tflow = 0, tcost = 0;
    while (dijkstra(s, t)) {
      T now = INF;
      for (int node = t; node != s; node = par[node]) 
        now = min(now, cap[par[node]][node] - flow[par[node]][node]);
      assert(now > 0);
      for (int node = t; node != s; node = par[node]) {
        flow[par[node]][node] += now;
        flow[node][par[node]] -= now;
        tcost += now * cost[par[node]][node];
      }
      tflow += now;
    }
    return {tflow, tcost};
  }
  // If some costs can be negative, call this before maxflow:
  void SetPi(int s) { // (otherwise, leave this out)
    dist.assign(n, INF); dist[s] = 0;
    int it = n, ch = 1;
    while (ch-- && it--)
      for (int i = 0; i < n; ++i)
        for (auto j : graph[i])
          ch |= relax(i, j);
    assert(it >= 0); // negative cost cycle
    swap(pi, dist);
  }
};

int main() {
  ifstream cin("fmcm.in");
  ofstream cout("fmcm.out");

  int n, m, s, t; cin >> n >> m >> s >> t;
  MFMC F(n);
  for (int i = 0; i < m; ++i) {
    int a, b, c, k; cin >> a >> b >> c >> k;
    F.AddEdge(a - 1, b - 1, c, k);
  }
  F.SetPi(s - 1);
  cout << F.Compute(s - 1, t - 1).second << endl;
  return 0;
}