#include <iostream>
#include <vector>
#include <cstdio>
#include <queue>
using namespace std;
struct MCMF {
const long long INFLL = (long long) 1e18;
const int INFINT = (int) 1e9;
int n, s, d;
struct Edge {
int from, to, cap, cost;
};
vector<Edge> edges;
vector<int> deg;
vector<int> verts;
vector<int> parrent;
vector<long long> mincost;
vector<vector<int>> g;
MCMF(int n, int m, int s, int d) : n(n), s(s), d(d), deg(n, 0), g(n), mincost(n), parrent(n) {
edges.reserve(m);
}
void add(int a, int b, int cap, int cost) {
edges.push_back({ a, b, cap, cost });
edges.push_back({ b, a, 0, -cost });
verts.push_back(a);
verts.push_back(b);
deg[a]++;
deg[b]++;
}
pair<long long, long long> get() {
for (int i = 0; i < n; i++) g[i].reserve(deg[i]);
for (int i = 0; i < (int)verts.size(); i++) g[verts[i]].push_back(i);
long long flow = 0, bestcostforflow = 0;
while (1) {
queue<int> q;
for (int i = 0; i < n; i++) mincost[i] = INFLL;
q.push(s);
mincost[s] = 0;
while (!q.empty()) {
int a = q.front();
q.pop();
for (auto& i : g[a]) {
if (edges[i].cap) {
int b = edges[i].to;
long long value_b = mincost[a] + edges[i].cost;
if (value_b < mincost[b]) {
mincost[b] = value_b;
q.push(b);
parrent[b] = i;
}
}
}
}
if (mincost[d] == INFLL) break;
int mn = INFINT;
long long sumcost = 0;
vector<int> path;
for (int i = d; i != s; i = edges[(parrent[i] ^ 1)].to) {
path.push_back(parrent[i]);
mn = min(mn, edges[parrent[i]].cap);
sumcost += edges[parrent[i]].cost;
}
for (auto& i : path) {
edges[i].cap -= mn;
edges[i ^ 1].cap += mn;
}
flow += mn;
bestcostforflow += (long long) mn * sumcost;
}
return { flow, bestcostforflow };
}
};
int main() {
freopen ("fmcm.in", "r", stdin);
freopen ("fmcm.out", "w", stdout);
int n, m, s, d;
scanf("%d %d %d %d", &n, &m, &s, &d);
s--;
d--;
MCMF flow(n, m, s, d);
while (m--) {
int x, y, a, b;
scanf("%d %d %d %d", &x, &y, &a, &b);
x--;
y--;
flow.add(x, y, a, b);
}
printf("%lld\n", flow.get().second);
}