#include <cmath>
#include <functional>
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <list>
#include <time.h>
#include <math.h>
#include <random>
#include <deque>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <cassert>
#include <chrono>
#include <complex>
#include <cstring>
#include <numeric>
using namespace std;
struct MCMF
{
const int INF = (int)1e9 + 7;
struct Edge
{
int to, cap, cost;
};
int n;
int s;
int d;
vector<Edge> edges;
vector < vector<int>> g;
vector<int> dist;
vector<int> dist2;
vector<bool> inq;
vector<int> paredge;
void init(int nn, int ss, int dd)
{
n = nn;
s = ss;
d = dd;
s--;
d--;
assert(0 <= s && s < n);
assert(0 <= d && d < n);
edges.clear();
dist.clear();
dist2.clear();
g.clear();
inq.clear();
paredge.clear();
g.resize(n);
dist.resize(n);
inq.resize(n);
paredge.resize(n);
dist2.resize(n);
}
void addedge(int a, int b, int cap, int cost)
{
a--;
b--;
assert(0 <= a && a < n);
assert(0 <= b && b < n);
edges.push_back({ b, cap, cost });
edges.push_back({ a, 0, -cost });
g[a].push_back((int)edges.size() - 2);
g[b].push_back((int)edges.size() - 1);
}
void bellman()
{
for (int i = 0; i < n; i++) dist[i] = INF, inq[i] = 0;
queue<int> q;
auto relax = [&](int v, int val, int specedge)
{
assert(0 <= v && v < (int)dist.size());
assert(0 <= v && v < (int)inq.size());
if (val < dist[v])
{
dist[v] = val;
paredge[v] = specedge;
if (!inq[v]) inq[v] = 1, q.push(v);
}
};
relax(s, 0, -1);
while (!q.empty())
{
int a = q.front();
assert(inq[a]);
inq[a] = 0;
q.pop();
for (auto& i : g[a])
{
if (edges[i].cap)
{
relax(edges[i].to, dist[a] + edges[i].cost, i);
}
}
}
}
void spfa()
{
for (int i = 0; i < n; i++) dist2[i] = INF;
priority_queue<pair<int, int>> q;
auto relax = [&](int v, int val, int specedge)
{
assert(0 <= v && v < (int)dist.size());
assert(0 <= v && v < (int)inq.size());
if (val < dist2[v])
{
dist2[v] = val;
paredge[v] = specedge;
q.push({ -dist2[v], v });
}
};
relax(s, 0, -1);
while (!q.empty())
{
auto it = q.top();
q.pop();
int a =it.second;
if (-it.first != dist2[a])
{
continue;
}
for (auto& i : g[a])
{
if (edges[i].cap)
{
relax(edges[i].to, dist2[a] + edges[i].cost + (dist[a] - dist[edges[i].to]), i);
}
}
}
for (int i = 0; i < n; i++)
{
dist[i] = dist2[i] + dist[i];
}
}
pair<int, long long> solve()
{
int flow = 0;
long long cost = 0;
bellman();
while (1)
{
spfa();
if (dist2[d] == INF) break;
int mn = INF, curv = d;
while (curv != s)
{
mn = min(mn, edges[paredge[curv]].cap);
curv = edges[paredge[curv] ^ 1].to;
}
assert(mn > 0);
flow += mn;
cost += mn * (long long)dist[d];
curv = d;
while (curv != s)
{
edges[paredge[curv]].cap -= mn;
edges[paredge[curv]^1].cap += mn;
curv = edges[paredge[curv] ^ 1].to;
}
}
return { flow, cost };
}
};
signed main()
{
#ifdef ONPC
FILE* stream;
freopen_s(&stream, "input.txt", "r", stdin);
#else
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
#endif
int n, m, s, d;
cin >> n >> m >> s >> d;
MCMF f;
f.init(n, s, d);
for (int i = 0; i < m; i++)
{
int a, b, c, d;
cin >> a >> b >> c >> d;
f.addedge(a, b, c, d);
}
cout << f.solve().second << "\n";
return 0;
}