#include <bits/stdc++.h>
using namespace std;
using T = int;
const T INF = numeric_limits<T>::max() / 4;
struct MFMC {
struct Edge { int from, to, nxt; T flow, cap, cost; };
int n;
vector<int> graph, par;
vector<T> dist, pi;
vector<Edge> es;
MFMC(int n) : n(n), graph(n, -1), par(n), dist(n), pi(n) {}
void AddEdge(int a, int b, T cap, T cost) {
auto add = [&](int a, int b, T cap, T cost) {
es.push_back({a, b, graph[a], 0, cap, cost});
graph[a] = es.size() - 1;
};
add(a, b, cap, cost); add(b, a, 0, -cost);
}
bool relax(int ei) {
const auto &e = es[ei];
if (dist[e.from] == INF) return false;
T now = dist[e.from] + pi[e.from] - pi[e.to] + e.cost;
if (e.flow < e.cap && now < dist[e.to]) {
dist[e.to] = now; par[e.to] = ei;
return true;
}
return false;
}
bool dijkstra(int s, int t) {
dist.assign(n, INF); par.assign(n, -1);
priority_queue<pair<T, int>> pq;
dist[s] = 0; pq.emplace(0, s);
while (!pq.empty()) {
T d; int node; tie(d, node) = pq.top(); pq.pop();
// auto [d, node] = pq.top(); pq.pop();
if (dist[node] != -d) continue;
for (int ei = graph[node]; ei != -1; ei = es[ei].nxt)
if (relax(ei))
pq.emplace(-dist[es[ei].to], es[ei].to);
}
for (int i = 0; i < n; ++i)
pi[i] = min(pi[i] + dist[i], INF);
return par[t] != -1;
}
pair<T, T> Compute(int s, int t) {
T flow = 0, cost = 0;
while (dijkstra(s, t)) {
T now = INF;
for (int ei = par[t]; ei != -1; ei = par[es[ei].from])
now = min(now, es[ei].cap - es[ei].flow);
for (int ei = par[t]; ei != -1; ei = par[es[ei].from]) {
es[ ei ].flow += now;
es[ei^1].flow -= now;
cost += es[ei].cost * now;
}
flow += now;
}
return {flow, cost};
}
// If some costs can be negative, call this before maxflow:
void SetPi(int s) { // (otherwise, leave this out)
dist.assign(n, INF); dist[s] = 0;
int it = n, ch = 1;
while (ch-- && it--)
for (int ei = 0; ei < (int)es.size(); ++ei)
ch |= relax(ei);
assert(it >= 0); // negative cost cycle
pi = dist;
}
};
struct InParser {
FILE *fin;
char *buff;
int sp;
char read_ch() {
++sp;
if (sp == (1 << 16)) {
sp = 0;
fread(buff, 1, (1 << 16), fin);
}
return buff[sp];
}
InParser(const char* nume) {
fin = fopen(nume, "r");
buff = new char[1 << 16]();
sp = (1 << 16) - 1;
}
InParser& operator >> (int &n) {
char c;
while (!isdigit(c = read_ch()) && c != '-');
int sgn = 1;
if (c == '-') {
n = 0;
sgn = -1;
} else {
n = c - '0';
}
while (isdigit(c = read_ch())) {
n = 10 * n + c - '0';
}
n *= sgn;
return *this;
}
};
int main() {
InParser cin("fmcm.in");
ofstream cout("fmcm.out");
int n, m, s, t; cin >> n >> m >> s >> t;
MFMC F(n);
for (int i = 0; i < m; ++i) {
int a, b, c, k; cin >> a >> b >> c >> k;
F.AddEdge(a - 1, b - 1, c, k);
}
F.SetPi(s - 1);
cout << F.Compute(s - 1, t - 1).second << endl;
return 0;
}