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