Cod sursa(job #2770967)

Utilizator retrogradLucian Bicsi retrograd Data 24 august 2021 13:47:56
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.93 kb
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
const int INF = 1e9; // greater than sum(e.k), INF * sum(sup) should fit

struct NetworkSimplex {
  struct Edge { int a, b, c, k, f = 0; };

  int n;
  vector<int> sup, pei, depth, pi;
  vector<Edge> E;
  set<int> tree_es;
  vector<vector<int>> graph;
  vector<int> q;
  
  NetworkSimplex(int n) : 
    n(n), sup(n, 0), pei(n + 1, -1), 
    depth(n + 1, 0), pi(n + 1, 0), graph(n + 1) {}
  
  int AddEdge(int a, int b, int c, int k) {
    E.push_back({a, b, c, k});
    E.push_back({b, a, 0, -k});
    return E.size() - 2;
  }

  void build_tree() {
    for (int i = 0; i <= n; ++i)
      graph[i].clear();
    for (auto i : tree_es) 
      graph[E[i].a].push_back(i);
    q.assign(1, n);
    for (int i = 0; i <= n; ++i) {
      int node = q[i];
      for (auto ei : graph[node]) {
        auto& e = E[ei];
        int vec = e.b, k = e.k;
        if (ei == pei[node]) continue;
        pi[vec] = pi[node] + k;
        depth[vec] = 1 + depth[node];
        pei[vec] = (ei ^ 1);
        q.push_back(vec);
      }
    }
  }

  int pivot(int ein) {
    int f = E[ein].c - E[ein].f;
    pair<int, int> eout = {f, ein};
    auto walk = [&](int ei, int phase) {
      auto nxt = [&](int ei, int dir) {
        ei ^= dir;
        int res = E[ei].c - E[ei].f;
        if (phase == 0) {
          f = min(f, res);
          eout = min(eout, make_pair(res, ei));
        } else {
          E[ei].f += f;
          E[ei^1].f -= f;
        }
        ei ^= dir;
        return E[ei].b;
      };
      nxt(ei, 0);
      int a = E[ei].a, b = E[ei].b;
      while (a != b) {
        if (depth[a] > depth[b]) 
          a = nxt(pei[a], 1);
        else b = nxt(pei[b], 0);
      }
    };
    for (int phase : {0, 1}) 
      walk(ein, phase);
    tree_es.insert(ein); tree_es.insert(ein^1);
    tree_es.erase(eout.second); tree_es.erase(eout.second^1);
    return f;
  }

  ll Compute() {
    for (int i = 0; i < n; ++i) {
      int a = n, b = i; ll c = sup[i], k = -INF;
      if (c < 0) c *= -1, swap(a, b);
      int ei = AddEdge(a, b, c, k);
      tree_es.insert(ei);
      tree_es.insert(ei^1);
    }  
    
    ll answer = 0;
    while (true) { 
      build_tree();
      pair<int, int> ein = {0, -1};
      for (int i = 0; i < (int)E.size(); ++i) {
        auto& e = E[i];
        if (e.f < e.c)
          ein = min(ein, make_pair(pi[e.a] + e.k - pi[e.b], i));
        if (i % (3 * n) == 0 && ein.first > 0) break;
      }
      if (ein.first == 0) break;
      int flow = pivot(ein.second);
      answer += 1LL * flow * ein.first;
    }
    return answer;
  }
};

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

  int n, m, s, t; cin >> n >> m >> s >> t;
  NetworkSimplex NS(n);
  for (int i = 0; i < m; ++i) {
    int a, b, c, k; cin >> a >> b >> c >> k;
    NS.AddEdge(a - 1, b - 1, c, k);
  }
  int ed = NS.AddEdge(t - 1, s - 1, INF, -INF);
  cout << NS.Compute() + 1LL * INF * NS.E[ed].f << endl;

  return 0;
}