#include <bits/stdc++.h>
using namespace std;
class Edge
{
public:
int node;
int cost;
Edge()
{}
Edge(int n, int c)
{
node = n;
cost = c;
}
};
class Unit
{
public:
int cap;
int cost;
Unit()
{}
Unit(int f, int c)
{
cap = f;
cost = c;
}
};
class Comp
{
public:
bool operator()(Edge a, Edge b)
{
return a.cost > b.cost;
}
};
void reset(vector <int> &v)
{
for(unsigned i = 0; i < v.size(); i++)
v[i] = 0;
}
void reset(vector <bool> &v)
{
for(unsigned i = 0; i < v.size(); i++)
v[i] = false;
}
void vector_set(vector <int> &v, int value)
{
for(unsigned i = 0; i < v.size(); i++)
v[i] = value;
}
void Bellman(int start, vector <vector <Edge>> &path, vector <vector <Unit>> &flux, vector <int> &dist, vector <bool> &vis)
{
reset(vis);
vector_set(dist, numeric_limits<int>::max());
queue <int> q;
dist[start] = 0;
q.push(start);
vis[start] = true;
int now;
Edge vec;
while(!q.empty())
{
now = q.front();
q.pop();
vis[now] = false;
for(unsigned i = 0; i < path[now].size(); i++)
{
vec = path[now][i];
if(flux[now][vec.node].cap > 0 && dist[vec.node] > dist[now] + vec.cost)
{
dist[vec.node] = dist[now] + vec.cost;
if(!vis[vec.node])
{
q.push(vec.node);
vis[vec.node] = true;
}
}
}
}
}
bool Dijkstra(int start, int dest, vector <vector <Edge>> &path, vector <vector <Unit>> &flux, vector <int> &parent, vector <int> &dist, vector <bool> &vis)
{
vector <int> dist_d(path.size(), numeric_limits<int>::max());
vector <int> dist_u(path.size(), numeric_limits<int>::max());
reset(parent);
reset(vis);
priority_queue <Edge, vector <Edge>, Comp> q;
q.push(Edge(start, 0));
dist_d[start] = dist_u[start] = 0;
int now;
Edge vec;
while(!q.empty())
{
now = q.top().node;
q.pop();
for(unsigned i = 0; i < path[now].size(); i++)
{
vec = path[now][i];
if(!vis[vec.node] && flux[now][vec.node].cap > 0 && dist_d[vec.node] > dist_d[now] + vec.cost + dist[now] - dist[vec.node])
{
dist_d[vec.node] = dist_d[now] + vec.cost + dist[now] - dist[vec.node];
dist_u[vec.node] = dist_u[now] + vec.cost;
parent[vec.node] = now;
q.push(Edge(vec.node, dist_d[vec.node]));
}
}
vis[now] = true;
}
for(unsigned i = 0; i < dist.size(); i++)
dist[i] = dist_u[i];
if(dist_d[dest] == numeric_limits<int>::max())
return false;
else
return true;
}
void Update(int start, int dest, int &ans, vector <vector <Edge>> &path, vector <vector <Unit>> &flux, vector <int> &dist, vector <int> &parent)
{
int max_flux = numeric_limits<int>::max();
for(int now = parent[dest], vec = dest; vec != start; vec = now, now = parent[now])
{
max_flux = min(max_flux, flux[now][vec].cap);
}
for(int now = parent[dest], vec = dest; vec != start; vec = now, now = parent[now])
{
flux[now][vec].cap -= max_flux;
flux[vec][now].cap += max_flux;
}
ans += dist[dest] * max_flux;
}
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
int main()
{
int n, m, start, dest;
fin>>n>>m>>start>>dest;
vector <vector <Edge>> path(n + 1);
vector <vector <Unit>> flux(n + 1, vector <Unit> (n + 1, Unit(0, 0)));
for(int x, y, f, c; m; m--)
{
fin>>x>>y>>f>>c;
path[x].push_back(Edge(y, c));
path[y].push_back(Edge(x, -c));
flux[x][y] = Unit(f, c);
flux[y][x] = Unit(0, -c);
}
int ans = 0;
vector <int> dist(n + 1);
vector <int> parent(n + 1);
vector <bool> vis(n + 1);
Bellman(start, path, flux, dist, vis);
while(Dijkstra(start, dest, path, flux, parent, dist, vis))
{
Update(start, dest, ans, path, flux, dist, parent);
}
fout<<ans<<'\n';
return 0;
}