#include <bits/stdc++.h>
using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
#define dbg(x) cerr<<#x": "<<(x)<<endl
#define dbg_p(x) cerr<<#x": "<<(x).first<<' '<<(x).second<<endl
#define dbg_v(x, n) {cerr<<#x"[]: ";for(long long _=0;_<n;++_)cerr<<(x)[_]<<' ';cerr<<endl;}
#define all(v) v.begin(), v.end()
#define fi first
#define se second
template<typename T1, typename T2>
ostream& operator <<(ostream &out, const pair<T1, T2> &item) {
out << '(' << item.first << ", " << item.second << ')';
return out;
}
template <typename T>
ostream& operator <<(ostream &out, const vector<T>& v) {
for(const auto &item : v) out << item << ' ';
return out;
}
const int N = 360;
const int INF = 0x3f3f3f3f;
struct Edge {
int to, flow, cst;
};
int source, sink;
int d[N], reald[N], newd[N], prv[N], vis[N];
vector<int> adj[N];
vector<Edge> edges;
void addEdge(int a, int b, int cap, int cst) {
adj[a].push_back(edges.size());
edges.push_back({b, cap, cst});
adj[b].push_back(edges.size());
edges.push_back({a, 0, -cst});
}
void bellman() {
priority_queue<pii> q;
memset(d, INF, sizeof d);
for(d[source] = 0, q.push({0, source}); !q.empty(); ) {
int dst = -q.top().fi;
int v = q.top().se;
q.pop();
if(dst != d[v]) continue;
for(auto id : adj[v]) {
int u = edges[id].to;
if(edges[id].flow && d[u] > d[v] + edges[id].cst) {
d[u] = d[v] + edges[id].cst;
q.push({-d[u], u});
}
}
}
}
bool dijkstra() {
priority_queue<pii> q;
memset(newd, INF, sizeof newd);
memset(vis, 0, sizeof vis);
for(reald[source] = newd[source] = 0, q.push({0, source}); !q.empty(); ) {
int dst = -q.top().fi;
int v = q.top().se;
q.pop();
if(vis[v]) continue;
vis[v] = true;
for(auto id : adj[v]) {
int u = edges[id].to;
int w = d[v] + edges[id].cst - d[u];
if(edges[id].flow && newd[u] > newd[v] + w) {
newd[u] = newd[v] + w;
reald[u] = reald[v] + edges[id].cst;
prv[u] = id;
q.push({-newd[u], u});
}
}
}
return newd[sink] < INF;
}
int getFlow() {
int cst;
bellman();
for(cst = 0; dijkstra(); ) {
int pushed = INF;
for(int v = sink; v != source; v = edges[prv[v] ^ 1].to) {
pushed = min(pushed, edges[prv[v]].flow);
}
for(int v = sink; v != source; v = edges[prv[v] ^ 1].to) {
cst += pushed * edges[prv[v]].cst;
edges[prv[v]].flow -= pushed;
edges[prv[v] ^ 1].flow += pushed;
}
memcpy(d, reald, sizeof reald);
}
return cst;
}
int main()
{
ios_base::sync_with_stdio(false);
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
int n, m, a, b, cap, cst;
cin >> n >> m >> source >> sink;
for(int i = 1; i <= m; ++i) {
cin >> a >> b >> cap >> cst;
addEdge(a, b, cap, cst);
}
cout << getFlow() << '\n';
return 0;
}