#include <bits/stdc++.h>
using namespace std;
#define all(x) (x).begin(), (x).end()
const int MAXN = 355;
int dist[MAXN], real_d[MAXN], old[MAXN];
int t[MAXN];
vector< int > gr[MAXN];
int cap[MAXN][MAXN];
int cost[MAXN][MAXN];
inline void add(int a, int b, int c, int d) {
gr[a].emplace_back(b);
gr[b].emplace_back(a);
cap[a][b] = c;
cost[a][b] = d;
cost[b][a] = -d;
}
class cmp {
public:
const bool operator () (const pair< int, int > &a, const pair< int, int > &b) const {
return a.second > b.second;
}
};
bool dijkstra(int source, int target) {
memset(t, -1, sizeof t);
memset(dist, 0x3f, sizeof dist);
memset(real_d, 0, sizeof real_d);
priority_queue< pair< int, int >, vector< pair< int, int > >, cmp > h;
h.push({source, 0});
dist[source] = 0;
while(h.size()) {
int node, c;
tie(node, c) = h.top();
h.pop();
if(c != dist[node]) continue;
for(auto &x : gr[node]) {
int newcost = c + cost[node][x] + old[node] - old[x];
if(newcost < dist[x] && cap[node][x] > 0) {
dist[x] = newcost;
real_d[x] = real_d[node] + cost[node][x];
t[x] = node;
h.push({x, dist[x]});
}
}
}
memcpy(old, dist, sizeof old);
return t[target] != -1;
}
int main() {
#ifdef BLAT
freopen("input", "r", stdin);
#else
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
srand(time(nullptr));
int n, m;
cin >> n >> m;
int s, d;
cin >> s >> d;
for(int i = 0, a, b, c, d; i < m; ++i) {
cin >> a >> b >> c >> d;
add(a, b, c, d);
}
int ans = 0;
while(dijkstra(s, d)) {
int node = d;
int flow = 1e9;
while(node != s) {
flow = min(flow, cap[t[node]][node]);
node = t[node];
}
node = d;
while(node != s) {
cap[t[node]][node] -= flow;
cap[node][t[node]] += flow;
node = t[node];
}
ans += flow*real_d[d];
}
cout << ans << '\n';
return 0;
}