/*input
5 7 2 5
3 1 7 -1
1 4 3 0
3 4 3 -4
1 5 7 0
4 5 1 1
2 5 8 -3
2 3 4 -3
*/
#include <bits/stdc++.h>
using namespace std;
#define sp ' '
#define endl '\n'
#define fi first
#define se second
#define mp make_pair
#define N
#define bit(x,y) ((x>>y)&1LL)
#define loop(i,l,r) for(int i=(int)(l); i<=(int)(r); i++)
void read(int &number) {
bool negative = false;
int c;
number = 0;
c = getchar();
while (c == ' ' || c == '\n')
c = getchar();
if (c == '-') {
negative = true;
c = getchar();
}
for (; (c > 47 && c < 58); c = getchar())
number = number * 10 + c - 48;
if (negative)
number = -number;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &a) {
return os << '(' << a.first << ", " << a.second << ')';
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) {
os << '[';
for (unsigned int i = 0; i < a.size(); i++)
os << a[i] << (i < a.size() - 1 ? ", " : "");
os << ']';
return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &a) {
os << '{';
for (typename set<T>::iterator it = a.begin(); it != a.end(); it++) {
typename set<T>::iterator jt = it;
os << *it << (++jt != a.end() ? ", " : "");
}
os << '}';
return os;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, map<T1, T2> &a) {
os << "{\n";
for (typename map<T1, T2>::iterator it = a.begin(); it != a.end(); it++) {
typename map<T1, T2>::iterator jt = it;
os << " " << it->first << ": " << it->second << (++jt != a.end() ? ",\n" : "\n");
}
os << '}';
return os;
}
// Source: rng_58: http://codeforces.com/contest/277/submission/3212642
// Fast min cost max flow (Dijkstra)
// Index from 0
// NOTE!!!!!! Flow through both direction can be < 0
// --> need to be careful when trace
// Does not work when cost < 0
#define F_INF 1000000000
#define C_INF 1000000000
template<class Flow = int, class Cost = int>
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;
for (int i = 0; i < V; i++) used[i] = false;
for (int i = 0; i < V; i++) 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]));
}
}
}
for (int i = 0; i < V; i++) 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);
}
};
int n, m, S, T;
signed main() {
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
read(n); read(m); read(S); read(T);
MinCostFlow<> MCMF(n + 5, m + 5);
loop(i, 1, m) {
int u, v, cap, cost;
read(u); read(v); read(cap); read(cost);
MCMF.addEdge(u, v, cap, cost);
}
cout << MCMF.minCostFlow(S, T).se << endl;
}