Cod sursa(job #2591221)

Utilizator gabrielinelusGabriel-Robert Inelus gabrielinelus Data 30 martie 2020 00:45:10
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.99 kb
#include <iostream>
#include <fstream>
#include <limits>
#include <queue>
#include <vector>

using namespace std;

int Source, Sink, N, M;
vector<vector<int>> Flow, Capacity, Cost, Graph;
vector<int> daddy, old_dist, real_dist, DP;

void addEdge(int from, int to, int cap, int cst)
{
  Graph[from].emplace_back(to);
  Capacity[from][to] += cap;
  Cost[from][to] += cst;
}

void bellmanFord(int k)
{
  vector<bool> inQueue(N);
  queue<int> Queue;
  fill(old_dist.begin(), old_dist.end(), numeric_limits<int>::max()); 
  Queue.push(k);
  inQueue[k] = true;
  old_dist[k] = 0;

  while (!Queue.empty()) {
    k = Queue.front();
    Queue.pop();
    inQueue[k] = false;

    for (auto v: Graph[k])
      if (old_dist[v] > old_dist[k] + Cost[k][v] && Capacity[k][v] > Flow[k][v]) {
	old_dist[v] = old_dist[k] + Cost[k][v];

	if (inQueue[v]) continue;

	inQueue[v] = true;
	Queue.push(v);
      }
  }
}

bool dijkstra(int k)
{
  fill(DP.begin(), DP.end(), numeric_limits<int>::max());
  fill(real_dist.begin(), real_dist.end(), numeric_limits<int>::max());

  priority_queue<pair<int,int>> Heap;
  Heap.push({-0, k});
  DP[k] = 0;
  real_dist[k] = 0;

  while (!Heap.empty()) {
    k = Heap.top().second;
    int cost = -Heap.top().first;
    Heap.pop();

    if (DP[k] < cost) continue;
    if (k == Sink) continue;

    // old_dist[v] <= old_dist[k] + Cost[k][v] due to bellmanFord minimality
    // so Cost[k][v] + old_dist[k] - old_dist[v] >= 0
    for (auto v: Graph[k]) 
      if (DP[v] > DP[k] + Cost[k][v] + old_dist[k] - old_dist[v] && Capacity[k][v] > Flow[k][v]) {
	DP[v] = DP[k] + Cost[k][v] + old_dist[k] - old_dist[v];
	real_dist[v] = real_dist[k] + Cost[k][v];
	daddy[v] = k;
	Heap.push({-DP[v], v});
      }	
  }
  old_dist = real_dist;
  return DP[Sink] != numeric_limits<int>::max();
}

int main()
{
  ifstream fin("fmcm.in");
  ofstream fout("fmcm.out");

  fin.sync_with_stdio(false);
  fin.tie(0);
  fout.sync_with_stdio(false);
  fout.tie(0);

  fin >> N >> M >> Source >> Sink;
  --Source;
  --Sink;

  Graph.resize(N);
  Flow.resize(N);
  Capacity.resize(N);
  Cost.resize(N);
  daddy.resize(N);
  old_dist.resize(N);
  real_dist.resize(N);
  DP.resize(N);
  
  fill(Flow.begin(), Flow.end(), vector<int>(N));
  fill(Capacity.begin(), Capacity.end(), vector<int>(N));
  fill(Cost.begin(), Cost.end(), vector<int>(N));
  
  for (int i = 0; i < M; ++i) {
    int x, y, cap, cst;
    fin >> x >> y >> cap >> cst;
    --x;
    --y;
    addEdge(x, y, cap, cst);
    addEdge(y, x, 0, -cst);
  }

  int maxFlow = 0;
  int minCost = 0;

  bellmanFord(Source);
  while (dijkstra(Source)) {
    int bottleNeck = numeric_limits<int>::max();
    for (int k = Sink; bottleNeck > 0 && k != Source; k = daddy[k])
      bottleNeck = min(bottleNeck, Capacity[daddy[k]][k] - Flow[daddy[k]][k]);

    if (bottleNeck == 0) continue;

    for (int k = Sink; k != Source; k = daddy[k]) {
      Flow[daddy[k]][k] += bottleNeck;
      Flow[k][daddy[k]] -= bottleNeck;
    }

    minCost += bottleNeck * real_dist[Sink];
  }
  fout << minCost << "\n";
  return 0;
}