Pagini recente » Cod sursa (job #633847) | Cod sursa (job #587991) | Cod sursa (job #96586) | Cod sursa (job #266070) | Cod sursa (job #2900263)
/// 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";
}