#include <bits/stdc++.h>
using namespace std;
const int NMAX = 400, inf = 0x3f3f3f3f;
struct Edge {
int from, to, cap, cost, flow;
Edge *rev;
Edge(int from, int to, int cap, int cost) :
from(from),
to(to),
cap(cap),
cost(cost),
flow(0),
rev(0) {
}
};
int N, M, S, D;
vector<Edge *> G[NMAX];
void AddEdge(int from, int to, int cap, int cost) {
Edge *dir = new Edge(from, to, cap, cost);
Edge *rev = new Edge(to, from, 0, -cost);
dir->rev = rev;
rev->rev = dir;
G[from].push_back(dir);
G[to].push_back(rev);
}
int dist[NMAX];
bool inq[NMAX];
Edge *father[NMAX];
bool BellmanFord(int S, int D) {
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 (it->cap - it->flow == 0)
continue;
if (dist[it->to] > dist[it->from] + it->cost) {
dist[it->to] = dist[it->from] + it->cost;
father[it->to] = it;
if (inq[it->to] == 0) {
Q.push(it->to);
inq[it->to] = 1;
}
}
}
}
return dist[D] != inf;
}
int MaxFlowMinCost(int S, int D) {
int answer = 0;
while (BellmanFord(S, D)) {
int add = inf;
Edge *curr = father[D];
while (curr != 0) {
add = min(add, curr->cap - curr->flow);
curr = father[curr->from];
}
curr = father[D];
while (curr != 0) {
curr->flow += add;
curr->rev->flow -= add;
curr = father[curr->from];
}
answer += dist[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;
cin >> N >> M >> S >> D;
for (i = 1; i <= M; ++i) {
cin >> x >> y >> c >> z;
AddEdge(x, y, c, z);
}
cout << MaxFlowMinCost(S, D) << '\n';
return 0;
}