#include <bits/stdc++.h>
#define N 405
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
struct edge {
long long v,cap, flow,cost;
};
long long n;
vector<edge> e;
vector<long long>g[N];
long long dist[N], pot[N];
long long f[N];
bool vis[N];
long long par[N];
bool n2dijkstra = false;
///mcmf(int n) : n(n), g(n), dist(n), pot(n), f(n), vis(n), par(n) {}
void add_edge(ll u, ll v, ll cap, ll cost) {
ll k = e.size();
e.push_back({v, cap, 0, cost});
e.push_back({u, cap, cap, -cost});
g[u].push_back(k);
g[v].push_back(k ^ 1);
}
pair<long long, long long> solve(ll s, ll t) {
ll flow = 0;
long long cost = 0;
while(true) {
memset(dist,INF,sizeof(dist));
memset(vis, false,sizeof(vis));
dist[s] = 0;
f[s] = INF;
if(n2dijkstra) {
while(true) {
ll x = -1; ll d = INF;
for(ll i = 1; i <= n; i++) {
if(!vis[i] && dist[i] < d) {
x = i;
d = dist[x];
}
}
if(x == -1) break;
vis[x] = true;
for(ll i : g[x]) {
ll d2 = d + e[i].cost + pot[x] - pot[e[i].v];
if(!vis[e[i].v] && e[i].flow < e[i].cap && d2 < dist[e[i].v]) {
dist[e[i].v] = d2;
f[e[i].v] = min(f[x], e[i].cap - e[i].flow);
par[e[i].v] = i;
}
}
}
}else {
priority_queue<pair<ll, ll>, vector<pair<ll, ll> >, greater<pair<ll,ll> > > Q;
Q.push({0, s});
while(!Q.empty()) {
ll d; ll x;
tie(d, x) = Q.top(); Q.pop();
if(vis[x]) continue;
vis[x] = true;
for(ll i : g[x]) {
ll d2 = d + e[i].cost + pot[x] - pot[e[i].v];
if(!vis[e[i].v] && e[i].flow < e[i].cap && d2 < dist[e[i].v]) {
dist[e[i].v] = d2;
f[e[i].v] = min(f[x], e[i].cap - e[i].flow);
par[e[i].v] = i;
Q.push({d2, e[i].v});
}
}
}
}
if(!vis[t]) break;
for(ll i = 1; i <= n; i++) {
dist[i] += pot[i] - pot[s];
}
cost += 1ll*dist[t] * f[t];
flow += f[t];
ll x = t;
while(x != s) {
e[par[x]].flow += f[t];
e[par[x] ^ 1].flow -= f[t];
x = e[par[x] ^ 1].v;
}
swap(dist,pot);
}
return {flow, cost};
}
int main()
{
ll i,x,y,c,z,m,s,t;
fin>>n>>m>>s>>t;
while(m--)
{
fin>>x>>y>>c>>z;
add_edge(x,y,c,z);
}
fout<<solve(s,t).second;
return 0;
}