Cod sursa(job #2778976)

Utilizator FunnyStockyMihnea Andreescu FunnyStocky Data 2 octombrie 2021 14:19:30
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.58 kb
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>


using namespace std;

typedef long long ll;

const int N = 350 + 7;
const int INF = (int) 1e9;
int n, m, s, d, cap[N][N], cost[N][N], minDist[N], minCap[N], par[N], cur[N];
vector<int> g[N];
bool inq[N];

void bellman() {
  for (int i = 1; i <= n; i++) {
    minDist[i] = INF;
  }
  minDist[s] = 0;
  queue<int> q;
  q.push(s);
  inq[s] = 1;
  while (!q.empty()) {
    int a = q.front();
    inq[a] = 0;
    q.pop();
    for (auto &b : g[a]) {
      if (!cap[a][b]) continue;
      int upd = minDist[a] + cost[a][b];
      if (upd < minDist[b]) {
        minDist[b] = upd;
        par[b] = a;
        if (!inq[b]) {
          q.push(b);
          inq[b] = 1;
        }
      }
    }
  }
}

void dijkstra() {
  for (int i = 1; i <= n; i++) {
    cur[i] = INF;
  }
  minCap[s] = INF;
  cur[s] = 0;
  priority_queue<pair<int, int>> q;
  q.push({0, s});
  while (!q.empty()) {
    int a = q.top().second;
    int val = q.top().first;
    q.pop();
    if (val != -cur[a]) continue;
    for (auto &b : g[a]) {
      if (!cap[a][b]) continue;
      int upd = cur[a] + cost[a][b];
      if (upd < cur[b]) {
        cur[b] = upd;
        minCap[b] = min(minCap[a], cap[a][b]);
        par[b] = a;
        q.push({-cur[b], b});

      }
    }
  }
  for (int i = 1; i <= n; i++) {
    for (auto &j : g[i]) {
      cost[i][j] += cur[i] - cur[j];
    }
    minDist[i] += cur[i];
  }
}

int main() {
  //freopen ("input", "r", stdin);
  freopen ("fmcm.in", "r", stdin), freopen ("fmcm.out", "w", stdout);

  scanf("%d %d %d %d", &n, &m, &s, &d);
  for (int i = 1; i <= m; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    scanf("%d %d", &cap[x][y], &cost[x][y]);
    cost[y][x] = -cost[x][y];
    g[x].push_back(y);
    g[y].push_back(x);
  }


  bellman();
  for (int i = 1; i <= n; i++) {
    for (auto &j : g[i]) {
      cost[i][j] += minDist[i] - minDist[j];
    }
  }

  ll mincost = 0;

  while (1) {
    dijkstra();
    if (cur[d] == INF) {
      break;
    }
    mincost += (ll) minDist[d] * minCap[d];
    vector<int> path;
    {
      int vertex = d;
      while (vertex != s) {
        path.push_back(vertex);
        vertex = par[vertex];
      }
      path.push_back(s);
      reverse(path.begin(), path.end());
    }
    for (int i = 0; i + 1 < (int) path.size(); i++) {
      int x = path[i], y = path[i + 1];
      cap[x][y] -= minCap[d];
      cap[y][x] += minCap[d];
    }
  }

  printf("%lld\n", mincost);

  return 0;
}