Cod sursa(job #2900247)

Utilizator FunnyStockyMihnea Andreescu FunnyStocky Data 10 mai 2022 16:44:23
Problema Flux maxim de cost minim Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.35 kb
/// always:
#include <cstdio>
#include <string>

/// optional:
#include <cassert>
#include <cstring>
#include <iostream>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <queue>

bool home = 1;
using namespace std;

typedef long long ll;
const string TASKNAME="fmcm";

const int FN=350+7;
const int FM=12500+7;
const int INF=(int)1e9+7;

struct Edge {
  int to;
  int cap;
  int cost;
};

int fn,fm,fs,fd,best[FN],pare[FN];
bool inq[FN];
vector<int> g[FN];
Edge edges[FM];

void init(int n,int s,int d) {
  for (int i=1;i<=n;i++) g[i].clear();
  fn=n;
  fm=0;
  fs=s;
  fd=d;

  assert(1<=fs&&fs<=n);
  assert(1<=fd&&fd<=n);
}

void addEdge(int a,int b,int cap,int cost) {
  assert(1<=a&&a<=fn);
  assert(1<=b&&b<=fn);

  g[a].push_back(fm);
  g[b].push_back(fm+1);

  edges[fm++]={b, cap, cost};
  edges[fm++]={a, 0, -cost};
}

void bellman() {
  for (int i=1;i<=fn;i++) {
    best[i]=INF;
    inq[i]=0;
  }
  best[fs]=0;
  inq[fs]=1;
  queue<int> q;
  q.push(fs);
  while (!q.empty()) {
    int a=q.front();
    inq[a]=0;
    q.pop();
    for (auto &i:g[a]) {
      int b=edges[i].to;
      int cap=edges[i].cap;
      int cost=edges[i].cost;
      if (cap>0&&best[a]+cost<best[b]) {

        best[b]=best[a]+cost;
        pare[b]=i;
        if (inq[b]==0) inq[b]=1, q.push(b);
      }
    }
  }
}

pair<ll, ll> get() {
  ll flow=0;
  ll cost=0;

  while (1) {
    bellman();
    if (best[fd]==INF) break;
    int cap=INF;
    vector<int> path;
    int cur=fd;
    while (cur!=fs) {
      path.push_back(pare[cur]);
      cap=min(cap,edges[pare[cur]].cap);
      assert(edges[pare[cur]].to==cur);
      cur=edges[pare[cur]^1].to;
    }
    assert(cap>0);
    flow+=cap;
    cost+=best[fd]*(ll)cap;
    for (auto &i:path){
      assert(edges[i].cap-cap>=0);
      edges[i].cap-=cap;
      edges[i^1].cap+=cap;
    }
  }

  return {flow, cost};
}

signed main() {
#ifdef INFOARENA
  home = 0;
#endif

  if(!home) {
    freopen((TASKNAME + ".in").c_str(), "r", stdin);
    freopen((TASKNAME + ".out").c_str(), "w", stdout);
  }else{
    freopen ("I_am_iron_man", "r", stdin);
  }

  int n,m,s,d;
  cin>>n>>m>>s>>d;
  init(n,s,d);
  for (int i=1;i<=m;i++) {
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    addEdge(a,b,c,d);
  }
  cout<<get().second<<"\n";
}