#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
inline int next_int() {int d;scanf("%d", &d);return d;}
const int INF = 1 << 30;
struct MinCostMaxFlow {
int V, E, min_cost, max_flow;
vector<int> from, to, capacity, cost;
MinCostMaxFlow(int n) {
V = n, E = 0, min_cost = 0, max_flow = 0;
from.clear(), to.clear(), capacity.clear(), cost.clear();
}
void add_edge(int a, int b, int c, int d) {
E++, from.push_back(a), to.push_back(b), capacity.push_back(c), cost.push_back(+d);
E++, from.push_back(b), to.push_back(a), capacity.push_back(0), cost.push_back(-d);
}
void run(const int source, const int sink) {
while (true) {
vector<int> dist(V, INF), edge(V, -1);
dist[source] = 0;
for (int v = 0; v < V; v++) {
for (int e = 0; e < E; e++) {
int a = from[e], b = to[e], c = capacity[e], d = cost[e];
if (dist[a] < INF && dist[a] + d < dist[b] && c > 0) {
dist[b] = dist[a] + d;
edge[b] = e;
}
}
}
if (dist[sink] == INF) {
break;
}
int now = sink, path_flow = INF, path_cost = 0;
while (now != source) {
path_flow = min(path_flow, capacity[edge[now]]);
now = from[edge[now]];
}
now = sink;
while (now != source) {
capacity[edge[now] ^ 0] -= path_flow;
capacity[edge[now] ^ 1] += path_flow;
path_cost += cost[edge[now]] * path_flow;
now = from[edge[now]];
}
min_cost += path_cost;
max_flow += path_flow;
}
}
};
int main() {
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
int n = next_int();
int m = next_int();
int s = next_int() - 1;
int d = next_int() - 1;
MinCostMaxFlow mcmf(n);
for (int i = 0; i < m; i++) {
int x = next_int() - 1;
int y = next_int() - 1;
int c = next_int();
int z = next_int();
mcmf.add_edge(x, y, c, z);
}
mcmf.run(s, d);
printf("%d\n", mcmf.min_cost);
return 0;
}