Cod sursa(job #2691663)

Utilizator retrogradLucian Bicsi retrograd Data 29 decembrie 2020 16:04:21
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.72 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, nxt; T flow, cap, cost; };
  
  int n;
  vector<int> graph, par; 
  vector<T> dist, pi;
  vector<Edge> es;
  
  MFMC(int n) : n(n), graph(n, -1), par(n), dist(n), pi(n) {}
  
  void AddEdge(int a, int b, T cap, T cost) {
    auto add = [&](int a, int b, T cap, T cost) {
      es.push_back({a, b, graph[a], 0, cap, cost});
      graph[a] = es.size() - 1;
    };
    add(a, b, cap, cost); add(b, a, 0, -cost);
  }
  bool relax(int ei) {
    const auto &e = es[ei];
    if (dist[e.from] == INF) return false;
    T now = dist[e.from] + pi[e.from] - pi[e.to] + e.cost;
    if (e.flow < e.cap && now < dist[e.to]) {
      dist[e.to] = now; par[e.to] = ei;
      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 (int ei = graph[node]; ei != -1; ei = es[ei].nxt) 
        if (relax(ei)) 
          pq.emplace(-dist[es[ei].to], es[ei].to);
    }
    for (int i = 0; i < n; ++i)
      pi[i] = min(pi[i] + dist[i], INF);
    return par[t] != -1;
  }
  pair<T, T> Compute(int s, int t) {
    T flow = 0, cost = 0;
    while (dijkstra(s, t)) {
      T now = INF;
      for (int ei = par[t]; ei != -1; ei = par[es[ei].from]) 
        now = min(now, es[ei].cap - es[ei].flow);
      for (int ei = par[t]; ei != -1; ei = par[es[ei].from]) {
        es[ ei ].flow += now;
        es[ei^1].flow -= now;
        cost += es[ei].cost * now;
      }
      flow += now;
    }
    return {flow, cost};
  }
  // 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 ei = 0; ei < (int)es.size(); ++ei) 
        ch |= relax(ei);
    assert(it >= 0); // negative cost cycle
    pi = dist;
  }
};

void read(int& x) {
  char c; int sgn = 1;
  for (c = getchar(); !isdigit(c) && c != '-'; c = getchar());
  if (c == '-') sgn = -1, c = getchar();
  for (x = 0; isdigit(c); c = getchar())
    x = x * 10 + c - '0';
  x *= sgn;
}
 
int main() {
  freopen("fmcm.in", "r", stdin);
  ofstream cout("fmcm.out");
 
  int n, m, s, t; read(n); read(m); read(s); read(t);
  MFMC F(n);
  for (int i = 0; i < m; ++i) {
    int a, b, c, k; read(a); read(b); read(c); read(k);
    F.AddEdge(a - 1, b - 1, c, k);
  }
  F.SetPi(s - 1);
  cout << F.Compute(s - 1, t - 1).second << endl;
  return 0;
}