#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cmath>
#include <cstring>
#include <ctime>
#include <unordered_map>
#include <iomanip>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define all(v) (v).begin(),(v).end()
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int inf = (1<<29);
struct MCMaxFlow{
struct edge{
int to,c,cst;
edge(int to=0, int c=0, int cst=0) : to(to), c(c), cst(cst) {}
edge(){}
};
vector<edge> e;
set<pii> st;
vi di;
vector<vi> g;
int n,S,F,flow,cflow;
MCMaxFlow(int n, int S, int F){
this->n=n;
g.resize(n);
di.resize(n);
this->S=S,this->F=F;
}
void add_edge(int x, int y, int cp, int cst){
edge e1(y,cp,cst);
edge e2(x,0,-cst);
g[x].pb(e.size());
e.pb(e1);
g[y].pb(e.size());
e.pb(e2);
}
bool dijkstra(){
vi d(n),p(n),pe(n);
fill(all(d),inf);
d[S]=0;
st.clear();
st.insert({0,S});
vi real_d(n);
while (!st.empty()){
pii cr = *st.begin();
st.erase(st.begin());
int nod=cr.se;
real_d[nod]=d[nod]-di[nod];
for (int id : g[nod]){
int nxt = e[id].to;
int cst=d[nod]+e[id].cst-di[nod]+di[nxt];
if (e[id].c && cst<d[nxt]){
if (d[nxt]!=inf) st.erase({d[nxt],nxt});
d[nxt] = cst;
p[nxt]=nod;
pe[nxt]=id;
st.insert({d[nxt],nxt});
}
}
}
di = real_d;
if (d[F] == inf) return 0;
int minv = inf,cr=0;
for (cr=F; cr!=S; cr=p[cr])
minv=min(minv,e[pe[cr]].c);
flow+=minv;
cflow += minv*real_d[F];
for (cr = F; cr!=S; cr=p[cr]){
e[pe[cr]].c-=minv;
e[pe[cr]^1].c+=minv;
}
return 1;
}
int get_flow(){
flow=cflow=0;
bellman();
while (dijkstra()) ;
return flow;
}
void bellman(){
fill(all(di),inf);
di[S]=0;
vi q,nq;
vi v(n,0);
q.pb(S);
for (int i=1; i<=n; i++){
nq.clear();
for (int x : q){
for (int id : g[x]){
int nxt = e[id].to;
if (e[id].c && e[id].cst+di[x]<di[nxt]){
di[nxt]=e[id].cst+di[x];
if (!v[nxt]) nq.pb(nxt);
v[nxt]=1;
}
}
}
q.clear();
for (int x : nq){
v[x]=0;
q.pb(x);
}
}
}
};
int N,M,S,D;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
fin >> N >> M >> S >> D;
MCMaxFlow mxf(N+1,S,D);
while (M--){
int x,y,c,z;
fin >> x >> y >> c >> z;
mxf.add_edge(x,y,c,z);
}
mxf.get_flow();
fout << mxf.cflow << "\n";
return 0;
}