#include <bits/stdc++.h>
using namespace std;
ifstream f("fmcm.in");
ofstream g("fmcm.out");
// #define f cin
// #define g cout
const int nmax = 360;
struct edge
{
int to, capacity, flow, weight, residual;
int remaining_capacity() const
{
return capacity - flow;
}
edge(int _to, int _cap, int _flow, int _we, int _res)
{
to = _to;
capacity = _cap;
flow = _flow;
weight = _we;
residual = _res;
}
};
vector<edge> v[nmax];
int n, m, source, sink, final_cost, potential[nmax], dp[nmax], realc[nmax];
pair<int, int> pre[nmax]; // nod,poz
void bellman_ford();
bool dijkstra();
int32_t main()
{
f >> n >> m >> source >> sink;
for (int x, y, c, d, ax1, ax2; m; m--)
{
f >> x >> y >> c >> d;
ax1 = v[y].size();
ax2 = v[x].size();
v[x].push_back(edge(y, c, 0, d, ax1));
v[y].push_back(edge(x, 0, 0, -d, ax2));
}
bellman_ford();
while (dijkstra())
;
g << -final_cost;
return 0;
}
void bellman_ford()
{
memset(potential, 0x3f3f3f3f, sizeof potential);
queue<int> q;
vector<bool> inq(nmax, false);
q.push(source);
potential[source] = 0;
inq[source] = 1;
while (!q.empty())
{
static int ac, nc;
ac = q.front();
q.pop();
for (const edge &i : v[ac])
if (i.capacity)
{
nc = potential[ac] + i.weight;
if (nc < potential[i.to])
{
potential[i.to] = nc;
if (inq[i.to])
continue;
inq[i.to] = 1;
q.push(i.to);
}
}
}
}
bool dijkstra()
{
memset(dp, 0x3f3f3f3f, sizeof dp);
// memset(realc, 0x3f3f3f3f, sizeof realc);
realc[source] = dp[source] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push({0, source});
while (!pq.empty())
{
static int nod, cst, ne, ur;
nod = pq.top().second;
cst = pq.top().first;
pq.pop();
if (cst != dp[nod])
continue;
for (int i = 0; i < (int)v[nod].size(); i++)
if (v[nod][i].remaining_capacity())
{
ur = v[nod][i].to;
ne = dp[nod] + v[nod][i].weight + potential[nod] - potential[ur];
if (ne < dp[ur])
{
dp[ur] = ne;
realc[ur] = realc[nod] + v[nod][i].weight;
pre[ur] = {nod, i};
pq.push({ne, ur});
}
}
}
if (dp[sink] == (0x3f3f3f3f))
return 0;
memcpy(potential, realc, sizeof potential);
int mnm = INT_MAX;
for (int ax = sink; ax != source; ax = pre[ax].first)
mnm = min(mnm, v[pre[ax].first][pre[ax].second].remaining_capacity());
final_cost += mnm * realc[sink];
for (int ax = sink, re, pr; ax != source; ax = pre[ax].first)
{
v[pre[ax].first][pre[ax].second].flow -= mnm;
re = v[pre[ax].first][pre[ax].second].to;
pr = v[pre[ax].first][pre[ax].second].residual;
v[re][pr].flow += mnm;
}
return 1;
}