#include "bits/stdc++.h"
using namespace std;
#define int long long
#define FOR(i, a, b) for (int i = (a), _##i = (b); i <= _##i; ++i)
#define FORD(i, a, b) for (int i = (a), _##i = (b); i >= _##i; --i)
#define REP(i, a) for (int i = 0, _##i = (a); i < _##i; ++i)
#define REPD(i,n) for(int i = (n)-1; i >= 0; --i)
#define DEBUG(X) { cerr << #X << " = " << (X) << endl; }
#define PR(A, n) { cerr << #A << " = "; FOR(_, 1, n) cerr << A[_] << ' '; cerr << endl; }
#define PR0(A, n) { cerr << #A << " = "; REP(_, n) cerr << A[_] << ' '; cerr << endl; }
#define sqr(x) ((x) * (x))
#define ll long long
#define double long double
typedef pair<int, int> II;
#define __builtin_popcount __builtin_popcountll
#define SZ(x) ((int)(x).size())
#define ALL(a) (a).begin(), (a).end()
#define MS(a,x) memset(a, x, sizeof(a))
#define next ackjalscjaowjico
#define prev ajcsoua0wucckjsl
#define y1 alkscj9u20cjeijc
#define left lajcljascjljl
#define right aucouasocjolkjl
#define y0 u9cqu3jioajc
#define TWO(X) (1LL<<(X))
#define CONTAIN(S,X) ((S) & TWO(X))
int rand16() {
return rand() & (TWO(16) - 1);
}
int my_rand() {
return rand16() << 32 | rand16() << 16 | rand16();
}
double safe_sqrt(double x) { return sqrt(max((double)0.0, x)); }
int GI(int& x) { return scanf("%lld", &x); }
#define F_INF 1000111000LL
#define C_INF 1000111000LL
template<class Flow = long long, class Cost = long long>
struct MinCostFlow {
int V, E;
vector<Flow> cap;
vector<Cost> cost;
vector<int> to, prev;
vector<Cost> dist, pot;
vector<int> last, path, used;
priority_queue< pair<Cost, int> > q;
MinCostFlow(int V, int E) : V(V), E(0), cap(E*2,0), cost(E*2,0), to(E*2,0), prev(E*2,0),
dist(V,0), pot(V,0), last(V, -1), path(V,0), used(V,0) {}
int addEdge(int x, int y, Flow f, Cost c) {
cap[E] = f; cost[E] = c; to[E] = y; prev[E] = last[x]; last[x] = E; E++;
cap[E] = 0; cost[E] = -c; to[E] = x; prev[E] = last[y]; last[y] = E; E++;
return E - 2;
}
pair<Flow, Cost> search(int s, int t) {
Flow ansf = 0; Cost ansc = 0;
REP(i,V) used[i] = false;
REP(i,V) dist[i] = C_INF;
dist[s] = 0; path[s] = -1; q.push(make_pair(0, s));
while (!q.empty()) {
int x = q.top().second; q.pop();
if (used[x]) continue; used[x] = true;
for(int e = last[x]; e >= 0; e = prev[e]) if (cap[e] > 0) {
Cost tmp = dist[x] + cost[e] + pot[x] - pot[to[e]];
if (tmp < dist[to[e]] && !used[to[e]]) {
dist[to[e]] = tmp;
path[to[e]] = e;
q.push(make_pair(-dist[to[e]], to[e]));
}
}
}
REP(i,V) pot[i] += dist[i];
if (used[t]) {
ansf = F_INF;
for(int e=path[t]; e >= 0; e=path[to[e^1]]) ansf = min(ansf, cap[e]);
for(int e=path[t]; e >= 0; e=path[to[e^1]]) { ansc += cost[e] * ansf; cap[e] -= ansf; cap[e^1] += ansf; }
}
return make_pair(ansf, ansc);
}
pair<Flow, Cost> minCostFlow(int s, int t) {
Flow ansf = 0; Cost ansc = 0;
while (1) {
pair<Flow, Cost> p = search(s, t);
if (!used[t]) break;
ansf += p.first; ansc += p.second;
}
return make_pair(ansf, ansc);
}
};
int32_t main() {
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout << (fixed) << setprecision(9) << boolalpha;
int n, m, s, t;
while (cin >> n >> m >> s >> t) {
--s; --t;
MinCostFlow<int,int> flow(n, m);
FOR(i,1,m) {
int u, v, fl, c; cin >> u >> v >> fl >> c;
--u;
--v;
flow.addEdge(u, v, fl, c);
}
auto res = flow.minCostFlow(s, t);
cout << res.second << endl;
}
}