Cod sursa(job #2875856)

Utilizator NanuGrancea Alexandru Nanu Data 22 martie 2022 14:43:05
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.6 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

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

#define DIM 350
#define INF (1LL << 30)
typedef pair<int, int> PII;

int n, m, S, D, total, CostMin;
bool sel[DIM + 1];
int dist[DIM + 1], t[DIM + 1];
int C[DIM + 1][DIM + 1], F[DIM + 1][DIM + 1], Cost[DIM + 1][DIM + 1];
vector <int> G[DIM + 1];
priority_queue <PII, vector<PII>, greater<PII>> PQ;

static inline void Bellman_Ford(int S) {
  for(int i = 1; i <= n; i++)
    dist[i] = INF;
  dist[S] = 0;

  queue<int> Q;
  Q.push(S);
  sel[S] = 1;
  while(!Q.empty()) {
    int nod = Q.front();
    sel[nod] = 0;
    Q.pop();

    for(auto e : G[nod])
      if(C[nod][e] > F[nod][e] && dist[e] > dist[nod] + Cost[nod][e]) {
        dist[e] = dist[nod] + Cost[nod][e];
        if(!sel[e]) {
          sel[e] = 1;
          Q.push(e);
        }
      }
  }
}

static inline bool Dijkstra(int S, int D) {
  for(int i = 1; i <= n; i++)
    if(dist[i] != INF)
      for(auto e : G[i])
        if(dist[e] != INF)
          Cost[i][e] += dist[i] - dist[e]; //fac toate costurile pozitive;

  for(int i = 1; i <= n; i++)
    dist[i] = INF;

  for(int i = 1; i <= n; i++)
    t[i] = 0;
 
  dist[S] = 0;
  PQ.push({0, S});    //retin distanta si nodul;
  while(!PQ.empty()) {
    int nod = PQ.top().second;
    int c = PQ.top().first;
    PQ.pop();

    if(c > dist[nod])
      continue;

    for(auto e : G[nod])
      if(C[nod][e] > F[nod][e] && dist[e] > Cost[nod][e] + dist[nod]) {
        t[e] = nod;
        dist[e] = Cost[nod][e] + dist[nod];
        PQ.push({dist[e], e});
      }
  }

  return (dist[D] != INF);    //daca am ajuns la destinatie;
}

static inline void Flux_Maxim(int S, int D) {
  total = dist[D];
  for(int drum = Dijkstra(S, D); drum; drum = Dijkstra(S, D)) {
    int fluxmin = INF;
    int nod = D;
    while(nod != S) {
      fluxmin = min(fluxmin, C[t[nod]][nod] - F[t[nod]][nod]);
      nod = t[nod];
    }
   
    nod = D;
    while(nod != S) {
      F[t[nod]][nod] += fluxmin;
      F[nod][t[nod]] -= fluxmin;
      nod = t[nod];
    }

    total += dist[D];
    CostMin += total * fluxmin;
  }
}

int main() {
  fin >> n >> m >> S >> D;
  for(int i = 1; i <= m; i++) {
    int x, y, cap, c;

    fin >> x >> y >> cap >> c;
    G[x].push_back(y);
    G[y].push_back(x);

    C[x][y] = cap;
    Cost[x][y] = c;
    Cost[y][x] = -c;
  }

  //retin distantele minime de la S la restul nodurilor;
  Bellman_Ford(S);
  Flux_Maxim(S, D);
  fout << CostMin;

  return 0;
}