#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
#include <bitset>
#include <cstring>
#define Nmax 360
#define INF 0x3f3f3f3f
using namespace std;
struct edge{
int a,b;
int capacity;
int flow;
int cost;
edge(){
a = b = capacity = flow = cost = 0;
}
}E[25500];
int N,M,S,D,nr = -1;
int old_dist[Nmax];
int real_dist[Nmax];
int dist[Nmax];
int daddy[Nmax];
vector<pair<int,int> > G[Nmax];
queue<int> Q;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > Heap;
bitset<Nmax>inQ;
void add_edge(int a,int b,int c, int z)
{
++nr;
E[nr].a = a;
E[nr].b = b;
E[nr].capacity = c;
E[nr].cost = z;
G[a].push_back(make_pair(b,nr));
}
void read()
{
scanf("%d%d%d%d",&N,&M,&S,&D);
int a,b,c,z;
for(int i = 1; i <= M; ++i)
{
scanf("%d%d%d%d",&a,&b,&c,&z);
add_edge(a,b,c,z);
add_edge(b,a,0,-z);
}
}
void get_old_dist()
{
memset(old_dist,INF,sizeof(old_dist));
old_dist[S] = 0;
Q.push(S);
int k;
while(!Q.empty())
{
k = Q.front(); Q.pop();
for(vector<pair<int,int> >::iterator it = G[k].begin(); it != G[k].end(); ++it)
if(old_dist[it->first] > old_dist[k] + E[it->second].cost)
{
old_dist[it->first] = old_dist[k] + E[it->second].cost;
if(inQ[it->first]) continue;
inQ[it->first] = 1;
Q.push(it->first);
}
}
}
bool dijkstra()
{
memset(real_dist,INF,sizeof(real_dist));
memset(dist,INF,sizeof(dist));
dist[S] = real_dist[S] = 0;
Heap.push(make_pair(0,S));
int k;
while(!Heap.empty())
{
k = Heap.top().second;
Heap.pop();
if(k == D) continue;
for(vector<pair<int,int> > ::iterator it = G[k].begin(); it != G[k].end(); ++it)
if(E[it->second].capacity - E[it->second].flow != 0 &&
dist[it->first] > dist[k] + E[it->second].cost + old_dist[k] - old_dist[it->first])
{
daddy[it->first] = it->second;
dist[it->first] = dist[k] + E[it->second].cost + old_dist[k] - old_dist[it->first];
real_dist[it->first] = real_dist[k] + E[it->second].cost;
Heap.push(make_pair(dist[it->first],it->first));
}
}
memcpy(old_dist,real_dist,sizeof(old_dist));
return real_dist[D] != INF;
}
void FLOW()
{
int minFLOW,minCOST = 0;
while(dijkstra())
{
if(real_dist[D] == INF) continue;
minFLOW = INF;
for(int nodc = D; nodc != S; nodc = E[daddy[nodc]].a + E[daddy[nodc]].b - nodc)
minFLOW = min(minFLOW,E[daddy[nodc]].capacity - E[daddy[nodc]].flow);
for(int nodc = D; nodc != S; nodc = E[daddy[nodc]].a + E[daddy[nodc]].b - nodc)
{
E[daddy[nodc]].flow += minFLOW;
E[daddy[nodc]^1].flow -= minFLOW;
}
minCOST += real_dist[D] * minFLOW;
}
printf("%d\n",minCOST);
}
int main()
{
freopen("fmcm.in","r",stdin);
freopen("fmcm.out","w",stdout);
read();
get_old_dist();
FLOW();
return 0;
}