Cod sursa(job #2433944)

Utilizator AlexPop28Pop Alex-Nicolae AlexPop28 Data 29 iunie 2019 21:15:29
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.19 kb
#include <bits/stdc++.h>
#define DEBUG(x) cerr << (#x) << ": " << (x) << '\n'

using namespace std;

vector<int> BellmanFord(int source, vector<vector<int>> &capacity,
  vector<vector<pair<int, int>>> &adj) {
  int n = adj.size();
  vector<int> q = {source};
  vector<int> dist(n, 1e9);
  vector<bool> in_queue(n);
  dist[source] = 0;
  for (int i = 0; i < (int)q.size(); ++i) {
    int node = q[i];
    in_queue[node] = false;
    for (auto &p : adj[node]) {
      int x, cost; tie(x, cost) = p;
      if (capacity[node][x] == 0) continue;
      if (dist[x] > dist[node] + cost) {
        dist[x] = dist[node] + cost;
        if (!in_queue[x]) {
          in_queue[x] = true;
          q.emplace_back(x);
        }
      }
    }
  }
  return dist;
}

bool CanIncreaseFlow(int source, int sink, vector<int> &parent,
  vector<int> &real_dist, vector<vector<pair<int, int>>> &adj,
    vector<vector<int>> &flow, vector<vector<int>> &capacity) {
            
  int n = adj.size();
  priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
  vector<int> mod_dist(n, 1e9);
  vector<int> dist(n, 1e9);
  mod_dist[source] = dist[source] = 0;
  pq.emplace(0, source);
  fill(parent.begin(), parent.end(), -1);
  parent[source] = -2;
  while (!pq.empty()) {
    int cost, node; tie(cost, node) = pq.top(); pq.pop();
    if (cost != mod_dist[node]) continue;
    for (auto &p : adj[node]) {
      int x, cost; tie(x, cost) = p;
      if (capacity[node][x] - flow[node][x] == 0) continue;
      cost += real_dist[node] - real_dist[x];
      if (mod_dist[x] > mod_dist[node] + cost) {
        mod_dist[x] = mod_dist[node] + cost;
        dist[x] = dist[node] + p.second;
        pq.emplace(mod_dist[x], x);
        parent[x] = node;
      }
    }
  }
  real_dist = move(dist);
  return parent[sink] != -1;
}

void IncreaseFlow(int source, int sink, pair<int, int> &max_flow_min_cost, 
  vector<int> &parent, vector<int> &dist, vector<vector<int>> &flow,
    vector<vector<int>> &capacity) {
  
  int node = sink, added_flow = 1e9;
  while (node != source) {
    added_flow = min(added_flow, 
      capacity[parent[node]][node] - flow[parent[node]][node]);
    node = parent[node];
  }
  max_flow_min_cost.first += added_flow;
  max_flow_min_cost.second += added_flow * dist[sink];
  node = sink;
  while (node != source) {
    flow[parent[node]][node] += added_flow;
    flow[node][parent[node]] -= added_flow;
    node = parent[node];
  }
}

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

  int n, m, source, sink; cin >> n >> m >> source >> sink; --source, --sink;
  vector<vector<pair<int, int>>> adj(n);
  vector<vector<int>> flow(n, vector<int>(n));
  vector<vector<int>> capacity(n, vector<int>(n));
  while (m--) {
    int u, v, cap, cost; cin >> u >> v >> cap >> cost; --u, --v;
    adj[u].emplace_back(v, +cost);
    adj[v].emplace_back(u, -cost);
    capacity[u][v] += cap;
  }
  auto real_dist = BellmanFord(source, capacity, adj);
  vector<int> parent(n);
  pair<int, int> max_flow_min_cost = {0, 0};
  while (CanIncreaseFlow(source, sink, parent, real_dist, adj, flow, capacity)) {
    IncreaseFlow(source, sink, max_flow_min_cost, parent, real_dist, flow, capacity);
  }
  cout << max_flow_min_cost.second << endl;
}