#include <algorithm>
#include <cstdio>
#include <cstring>
#include <bitset>
#include <vector>
#include <queue>
#define PII pair<int, int>
#define x first
#define y second
#define mp make_pair
using namespace std;
const int N=355, INF=0x3f3f3f3f;
vector <int> G[N];
bitset <N> v;
int Cost[N][N], C[N][N], F[N][N], dist[N], old_c[N], new_c[N], Tr[N];
int n, S, D, flow, flow_cost;
struct comp{
bool operator()(const PII &a, const PII &b) const
{
return a>b;
}
};
bool bellman_ford()
{
int nod;
memset(old_c, INF, sizeof(old_c));
old_c[S]=0;
queue <int> Q;
for(Q.push(S);!Q.empty();Q.pop())
{
nod=Q.front();
v[nod]=0;
for(auto p: G[nod])
{
if(!C[nod][p]) continue;
if(old_c[p]>old_c[nod]+Cost[nod][p])
{
old_c[p]=old_c[nod]+Cost[nod][p];
if(!v[p])
{
v[p]=1;
Q.push(p);
}
}
}
}
return (old_c[D]!=INF);
}
bool dijkstra()
{
int i, nod, d, cst, fmin;
priority_queue <PII, vector<PII>, comp> H;
memset(dist, INF, sizeof(dist));
dist[S]=0;
for(H.push(mp(0, S));!H.empty();)
{
nod=H.top().second;
d=H.top().first;
H.pop();
if(dist[nod]!=d) continue;
for(auto p: G[nod])
{
if(C[nod][p]==F[nod][p]) continue;
cst=dist[nod]+Cost[nod][p]+old_c[nod]-old_c[p];
if(dist[p]>cst)
{
dist[p]=cst;
new_c[p]=new_c[nod]+Cost[nod][p];
Tr[p]=nod;
H.push(mp(dist[p], p));
}
}
}
memcpy(old_c, new_c, sizeof(old_c));
if(dist[D]==INF) return false;
fmin=INF;
for(i=D;i!=S;i=Tr[i])
{
fmin=min(fmin, C[Tr[i]][i]-F[Tr[i]][i]);
}
flow+=fmin;
flow_cost+=fmin*new_c[D];
for(i=D;i!=S;i=Tr[i])
{
F[Tr[i]][i]+=fmin;
F[i][Tr[i]]-=fmin;
}
return true;
}
int main()
{
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
int m, i, j, x, y;
scanf("%d%d%d%d", &n, &m, &S, &D);
while(m--)
{
scanf("%d%d%d%d", &x, &y, &i, &j);
G[x].push_back(y);
G[y].push_back(x);
C[x][y]=i;
Cost[x][y]=j;
Cost[y][x]=-j;
}
bellman_ford();
while(dijkstra());
printf("%d\n", flow_cost);
}