#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define MOD 1000000007
#define MAX 355
#define INF 1000000000
using namespace std;
int initial[MAX][MAX];
pair < int, int > h[MAX][MAX];
vector < int > v[MAX], a;
int dist[MAX], s, r = 0;
bool viz[MAX], gasit;
queue < int > q;
priority_queue < pair < int, int >, vector < pair < int, int > >, greater < pair < int, int > > > qq;
void dfsForFindingBottleNeck(int x, int prec);
void dfs(int x, int prec, int bottleNeck);
int main()
{
FILE *input = fopen("fmcm.in", "r");
ofstream cout ("fmcm.out");
int n, m, t, x, y, c, z;
fscanf(input, "%d %d %d %d", &n, &m, &s, &t);
//cin >> n >> m >> s >> t;
for(int i = 1; i <= m; i++)
{
fscanf(input, "%d %d %d %d", &x, &y, &c, &z);
//cin >> x >> y >> c >> z;
v[x].pb(y), v[y].pb(x);
initial[x][y] = z;
h[x][y] = {c, z};
h[y][x] = {0, -z};
}
// Rulam o data Bellman Ford, pentru a calcula vectorul dist.
for(int i = 1; i <= n; i++) dist[i] = INF;
dist[s] = 0;
q.push(s);
while(!q.empty())
{
x = q.front(), q.pop();
for(int it:v[x])
{
if(h[x][it].first > 0 && dist[x] + h[x][it].second < dist[it])
{
dist[it] = dist[x] + h[x][it].second;
q.push(it);
}
}
}
// Calculam primul pas: F1 (costul minim pentru ca un flux de 1 sa circule de la s la t.)
if(dist[t] != INF)
{
gasit = false;
a.clear();
dfsForFindingBottleNeck(t, -1);
//cout << *min_element(a.begin(), a.end()) << ' ';
dfs(t, -1, *min_element(a.begin(), a.end()));
//dfs(t, -1, 1);
// Modificam costurile muchiilor a.i. nicio muchie sa nu mai aiba costul negativ.
for(int i = 1; i <= n; i++)
for(int it:v[i])
h[i][it].second += dist[i] - dist[it];
}
while(dist[t] != INF)
{
for (int i = 1; i <= n; i++) dist[i] = INF, viz[i] = false;
dist[s] = 0;
qq.push({dist[s], s});
while(!qq.empty())
{
pair < int, int > x = qq.top();
qq.pop();
if (!viz[x.second])
{
viz[x.second] = true;
for (int it: v[x.second])
if (h[x.second][it].first > 0 && dist[x.second] + h[x.second][it].second < dist[it])
{
dist[it] = dist[x.second] + h[x.second][it].second;
qq.push({dist[it], it});
}
}
}
if(dist[t] != INF)
{
gasit = false;
a.clear();
dfsForFindingBottleNeck(t, -1);
//cout << *min_element(a.begin(), a.end()) << ' ';
dfs(t, -1, *min_element(a.begin(), a.end()));
//dfs(t, -1, 1);
for(int i = 1; i <= n; i++)
for(int it:v[i])
h[i][it].second += dist[i] - dist[it];
}
}
cout << r;
return 0;
}
void dfsForFindingBottleNeck(int x, int prec)
{
if(x != s)
{
for(int it:v[x])
if(it != prec && h[it][x].first >= 1 && dist[it] + h[it][x].second == dist[x])
{
a.pb(h[it][x].first);
dfsForFindingBottleNeck(it, x);
if(!gasit) a.pop_back();
else break;
}
}
else gasit = true;
}
void dfs(int x, int prec, int bottleNeck)
{
if(x != s)
{
for(int it:v[x])
if(it != prec && h[it][x].first >= bottleNeck && dist[it] + h[it][x].second == dist[x])
{
h[it][x].first -= bottleNeck, r += bottleNeck * initial[it][x];
h[x][it].first += bottleNeck, r -= bottleNeck * initial[x][it];
dfs(it, x, bottleNeck);
if(!gasit)
{
h[it][x].first += bottleNeck, r -= bottleNeck * initial[it][x];
h[x][it].first -= bottleNeck, r += bottleNeck * initial[x][it];
}
else break;
}
}
else gasit = true;
}
/*
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
*/