#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int NMAX = 400, inf = 0x3f3f3f3f;
int N, M, S, D;
int F[NMAX][NMAX], C[NMAX][NMAX];
vector<pair<int, int>> G[NMAX];
void AddEdge(int from, int to, int cap, int cost) {
C[from][to] = cap;
C[to][from] = 0;
G[from].push_back({to, cost});
G[to].push_back({from, -cost});
}
int dist[NMAX];
bool inq[NMAX];
void BellmanFord(int S) {
memset(dist, inf, sizeof dist);
dist[S] = 0;
queue<int> Q;
Q.push(S);
inq[S] = 1;
while (!Q.empty()) {
int now = Q.front();
Q.pop();
inq[now] = 0;
for (const auto &it: G[now]) {
if (C[now][it.x] == 0)
continue;
if (dist[it.x] > dist[now] + it.y) {
dist[it.x] = dist[now] + it.y;
if (inq[it.x] == 0) {
Q.push(it.x);
inq[it.x] = 1;
}
}
}
}
}
int dist2[NMAX], rdist[NMAX];
int father[NMAX];
bool Dijkstra(int S, int D) {
memset(dist2, inf, sizeof dist2);
memset(rdist, 0, sizeof rdist);
dist2[S] = 0;
priority_queue<pair<int, int>> PQ;
PQ.push({0, S});
while (!PQ.empty()) {
int cost, node;
tie(cost, node) = PQ.top();
PQ.pop();
if (node == D)
return 1;
if (dist2[node] != -cost)
continue;
for (const auto &it: G[node]) {
if (C[node][it.x] - F[node][it.x] == 0)
continue;
if (dist2[it.x] > dist2[node] + it.y + dist[node] - dist[it.x]) {
dist2[it.x] = dist2[node] + it.y + dist[node] - dist[it.x];
rdist[it.x] = rdist[node] + it.y;
father[it.x] = node;
PQ.push({-dist2[it.x], it.x});
}
}
}
return 0;
}
int MaxFlowMinCost(int S, int D) {
int answer = 0;
BellmanFord(S);
while (Dijkstra(S, D)) {
int add = inf;
int curr = D;
while (father[curr] != 0) {
add = min(add, C[father[curr]][curr] - F[father[curr]][curr]);
curr = father[curr];
}
curr = D;
while (father[curr] != 0) {
F[father[curr]][curr] += add;
F[curr][father[curr]] -= add;
curr = father[curr];
}
answer += rdist[D] * add;
}
return answer;
}
int main() {
assert(freopen("fmcm.in", "r", stdin));
assert(freopen("fmcm.out", "w", stdout));
int i;
int x, y, c, z;
scanf("%d %d %d %d", &N, &M, &S, &D);
for (i = 1; i <= M; ++i) {
scanf("%d %d %d %d", &x, &y, &c, &z);
AddEdge(x, y, c, z);
}
cout << MaxFlowMinCost(S, D) << '\n';
return 0;
}