Cod sursa(job #2900263)

Utilizator FunnyStockyMihnea Andreescu FunnyStocky Data 10 mai 2022 17:20:51
Problema Flux maxim de cost minim Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.42 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=2*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],init_best[FN],tv[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};
}

struct T {
  int vertex;
};

bool operator < (T a,T b) {
  if (best[a.vertex]==best[b.vertex]) return best[a.vertex]<best[b.vertex];
  return tv[a.vertex]<tv[b.vertex];
}

vector<int> order;

void pl(int a) {
  if (tv[a]>0) return;
  for (auto &i:g[a]) {
    int b=edges[i].to;
    int cap=edges[i].cap;
    if (cap>0) {
      pl(b);
    }
  }
  order.push_back(a);
  tv[a]=(int)order.size();
}

void bellman1() {
  for (int i=1;i<=fn;i++) best[i]=INF;
  best[fs]=0;

  pl(fs);
  reverse(order.begin(),order.end());

  for (auto &a:order){
    for (auto &i:g[a]) {
      int b=edges[i].to;
      int cap=edges[i].cap;
      int cost=edges[i].cost+init_best[a]-init_best[b];
      if (cap>0&&best[a]+cost<best[b]) {
        best[b]=best[a]+cost;
        pare[b]=i;
      }
    }
  }
}

void bellman2() {
  for (int i=1;i<=fn;i++) {
    init_best[i]=best[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+init_best[a]-init_best[b];
      if (cap>0) {
        assert(cost>=0);
      }
      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);
      }
    }
  }

  for (int i=1;i<=fn;i++) {
    if (best[i]==INF) continue;
    best[i]=best[i]-init_best[fs]+init_best[i];
  }
}

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

  bellman1();

  while (1) {
    bellman2();
    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";
}