#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define INF 1000000
using namespace std;
vector <int> g[1001];
vector <int> :: iterator Vecin;
queue <int> q;
int flux[1001][1001], capacitate[1001][1001], heap[1001], poz[1001], tata[1001], cost[1001][1001], Cost[1001], n, sursa, destinatie, nr=0, s=0, CostMin=0, sol;
bool used[1001];
void swap (int x, int y)
{
int aux=poz[heap[x]];
poz[heap[x]]=poz[heap[y]];
poz[heap[y]]=aux;
aux=heap[x];
heap[x]=heap[y];
heap[y]=aux;
}
void heapup (int x)
{
if (x==1) return;
if (Cost[heap[x]]<Cost[heap[x/2]])
{
swap(x,x/2);
heapup(x/2);
}
}
void heapdown(int x)
{
int st, dr;
if (x*2>nr) return;
st=Cost[heap[x*2]];
if (x*2+1<=nr) dr=Cost[heap[x*2+1]];
else dr=st+1;
if (st<dr)
{
if (Cost[heap[x]]<=st) return;
swap(x,x*2);
heapdown(x*2);
}
else
{
if (Cost[heap[x]]<=dr) return;
swap(x,x*2+1);
heapdown(x*2+1);
}
}
bool dijkstra (void)
{
int i, j, Nod;
for (Nod=1; Nod<=n; Nod++)
{
if (Cost[Nod]>=INF) continue;
for (i=0; i<g[Nod].size(); i++)
{
if (Cost[g[Nod][i]]<INF) cost[Nod][g[Nod][i]]+=Cost[Nod]-Cost[g[Nod][i]];
}
}
memset(Cost,INF,sizeof(Cost)); memset(tata,0,sizeof(tata));
Cost[sursa]=0;
for (i=1; i<=n; i++)
{
heap[i]=i;
poz[i]=i;
}
swap(1,sursa); nr=n;
while (nr>0 && Cost[heap[1]]<INF)
{
Nod=heap[1];
swap(1,nr);
nr--;
heapdown(1);
for (j=0; j<g[Nod].size(); j++)
{
if (Cost[g[Nod][j]]>Cost[Nod]+cost[Nod][g[Nod][j]] && flux[Nod][g[Nod][j]]<capacitate[Nod][g[Nod][j]])
{
Cost[g[Nod][j]]=Cost[Nod]+cost[Nod][g[Nod][j]];
tata[g[Nod][j]]=Nod;
heapup(poz[g[Nod][j]]);
}
}
}
if (Cost[destinatie]<INF) return true;
else return false;
}
void bellmanford (void)
{
int nod, i;
while (!q.empty()) q.pop(); q.push(sursa);
memset(used,false,sizeof(used)); memset(Cost,INF,sizeof(Cost)); memset(tata,0,sizeof(tata));
used[sursa]=false; Cost[sursa]=0;
while (!q.empty())
{
nod=q.front();
q.pop();
used[nod]=false;
for (i=0; i<g[nod].size(); i++)
{
if (Cost[nod]+cost[nod][g[nod][i]]<Cost[g[nod][i]] && flux[nod][g[nod][i]]<capacitate[nod][g[nod][i]])
{
if (Cost[g[nod][i]]>=INF) Cost[g[nod][i]]=Cost[nod]+cost[nod][g[nod][i]];
else Cost[g[nod][i]]+=Cost[nod]+cost[nod][g[nod][i]];
if (!used[g[nod][i]])
{
used[g[nod][i]]=true;
q.push(g[nod][i]);
}
}
}
}
s=Cost[destinatie];
}
void flux_maxim (void)
{
int i, j, r;
while (dijkstra())
{
r=INF;
for (j=destinatie; j!=sursa; j=tata[j])
{
r=min(r,capacitate[tata[j]][j]-flux[tata[j]][j]);
}
for (j=destinatie; j!=sursa; j=tata[j])
{
flux[tata[j]][j]+=r;
flux[j][tata[j]]-=r;
}
s+=Cost[destinatie];
CostMin+=r*s;
sol=CostMin;
}
}
int main()
{
int m, i, x, y, z, t;
freopen("fmcm.in","r",stdin);
freopen("fmcm.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&sursa,&destinatie);
for (i=1; i<=m; i++)
{
scanf("%d%d%d%d",&x,&y,&z,&t);
capacitate[x][y]=z;
g[x].push_back(y);
g[y].push_back(x);
cost[x][y]=t;
cost[y][x]=-t;
}
bellmanford();
flux_maxim();
printf("%d",sol);
fclose(stdin);
fclose(stdout);
return 0;
}