#include <fstream>
#include <queue>
#include <cstring>
#include <cassert>
using namespace std;
#define NUME "fmcm"
ifstream fi(NUME".in");
ofstream fo(NUME".out");
#define MAXN 351
#define INF 0x3f3f3f3f
int N, M, S, D;
struct list { int nod, cost; list *r; } *L[MAXN];
int F[MAXN][MAXN], C[MAXN][MAXN];
int Dist[MAXN], T[MAXN], tCost;
#define avail(i, j) (C[i][j] - F[i][j])
struct dist_greater {
inline bool operator()(const int &A, const int &B) {
return Dist[A] > Dist[B];
}
};
int bellman(int S, int D)
{
int stop = 0, i, j;
memset(Dist, INF, sizeof(T));
Dist[S] = 0;
for (i = 1; i <= N && !stop; ++i) {
stop = 1;
for (j = 1; j <= N; ++j)
for (list *p = L[j]; p; p = p->r)
if (avail(j, p->nod) > 0 &&
Dist[p->nod] > Dist[j] + p->cost) {
Dist[p->nod] = Dist[j] + p->cost;
stop = 0;
}
}
tCost = Dist[D];
return stop;
}
int dijkstra(int S, int D)
{
// HACK
for (int i = 1; i <= N; ++i)
for (list *j = L[i]; j; j = j->r)
if (Dist[i] != INF && Dist[j->nod] != INF)
j->cost += Dist[i] - Dist[j->nod];
// Dijkstra
memset(Dist, INF, sizeof(T));
priority_queue<int, vector<int>, dist_greater> Q;
Q.push(S);
Dist[S] = 0;
while (!Q.empty()) {
int x = Q.top(); Q.pop();
for (list *p = L[x]; p; p = p->r) {
if (avail(x, p->nod) > 0 && Dist[p->nod] > Dist[x] + p->cost) {
Dist[p->nod] = Dist[x] + p->cost;
T[p->nod] = x;
Q.push(p->nod);
}
}
}
return Dist[D];
}
void push(int x, int y, int c) {
list *p = new list;
*p = (list) { y, c, L[x] };
L[x] = p;
}
void fluxul(int S, int D)
{
int f, c, r, dist, i;
for (f = c = 0; (dist = dijkstra(S, D)) != INF;
f += r, tCost += dist, c += r*tCost) {
r = INF;
for (i = D; i != S; i = T[i])
r = min(r, avail(T[i], i));
for (i = D; i != S; i = T[i])
F[ T[i] ][i] += r, F[i][ T[i] ] -= r;
}
fo << c << "\n";
}
void citirea()
{
int i;
fi >> N >> M >> S >> D;
while (M--) {
int x, y, c, cost;
fi >> x >> y >> c >> cost;
push(x, y, cost);
push(y, x, -cost);
C[x][y] = c;
}
}
int main()
{
citirea();
assert(bellman(S, D)); // anti-cicluri
fluxul(S, D);
return 0;
}