#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
const int MAXN = 3e2 + 5e1;
const int INF = 0x3f3f3f3f;
struct Edge {
int u, c;
bool operator <(const Edge &aux) const {
return c > aux.c;
}
};
std::vector <int> g[MAXN + 1];
int flow[MAXN + 1][MAXN + 1], cap[MAXN + 1][MAXN + 1],
fath[MAXN + 1], vis[MAXN + 1], odist[MAXN + 1],
rdist[MAXN + 1], ddist[MAXN + 1],
cost[MAXN + 1][MAXN + 1];
std::queue <int> q;
std::priority_queue <Edge> pq;
static inline int min(int a, int b) {
return a > b ? b : a;
}
void bellman(int s, int d) {
int u;
memset(odist, INF, sizeof(odist));
odist[s] = 0;
q.push(s);
while (!q.empty()) {
u = q.front();
q.pop();
vis[u] = 0;
for (auto v: g[u]) {
if (flow[u][v] < cap[u][v] && odist[v] > odist[u] + cost[u][v]) {
odist[v] = odist[u] + cost[u][v];
fath[v] = u;
if (!vis[v]) {
q.push(v);
vis[v] = 1;
}
}
}
}
}
bool dijkstra(int s, int d) {
Edge x;
int tmp;
memset(ddist, INF, sizeof(ddist));
ddist[s] = rdist[s] = 0;
pq.push({s, 0});
while (!pq.empty()) {
x = pq.top();
pq.pop();
if (ddist[x.u] == x.c) {
for (auto v: g[x.u]) {
tmp = cost[x.u][v] + ddist[x.u] + odist[x.u] - odist[v];
if (flow[x.u][v] < cap[x.u][v] && tmp < ddist[v]) {
ddist[v] = tmp;
rdist[v] = rdist[x.u] + cost[x.u][v];
fath[v] = x.u;
pq.push({v, tmp});
}
}
}
}
memcpy(odist, rdist, sizeof(odist));
return (ddist[d] < INF);
}
int main() {
int n, m, s, d, u, v, c, z, fl, maxfl;
FILE *f = fopen("fmcm.in", "r");
fscanf(f, "%d%d%d%d", &n, &m, &s, &d);
for (int i = 0; i < m; ++i) {
fscanf(f, "%d%d%d%d", &u, &v, &c, &z);
g[u].push_back(v);
g[v].push_back(u);
cap[u][v] = c;
cost[u][v] = z;
cost[v][u] = -z;
}
fclose(f);
bellman(s, d);
maxfl = 0;
while (dijkstra(s, d)) {
u = d;
fl = INF;
while (u != s) {
fl = min(fl, cap[fath[u]][u] - flow[fath[u]][u]);
u = fath[u];
}
u = d;
while (u != s) {
flow[fath[u]][u] += fl;
flow[u][fath[u]] -= fl;
u = fath[u];
}
maxfl += fl * rdist[d];
}
f = fopen("fmcm.out", "w");
fprintf(f, "%d\n", maxfl);
fclose(f);
return 0;
}