#include <bits/stdc++.h>
#define DEBUG(x) cerr << (#x) << ": " << (x) << '\n'
using namespace std;
vector<int> BellmanFord(int source, vector<vector<int>> &capacity,
vector<vector<pair<int, int>>> &adj) {
int n = adj.size();
vector<int> q = {source};
vector<int> dist(n, 1e9);
vector<bool> in_queue(n);
dist[source] = 0;
for (int i = 0; i < (int)q.size(); ++i) {
int node = q[i];
in_queue[node] = false;
for (auto &p : adj[node]) {
int x, cost; tie(x, cost) = p;
if (capacity[node][x] == 0) continue;
if (dist[x] > dist[node] + cost) {
dist[x] = dist[node] + cost;
if (!in_queue[x]) {
in_queue[x] = true;
q.emplace_back(x);
}
}
}
}
return dist;
}
bool CanIncreaseFlow(int source, int sink, vector<int> &parent,
vector<int> &real_dist, vector<vector<pair<int, int>>> &adj,
vector<vector<int>> &flow, vector<vector<int>> &capacity) {
int n = adj.size();
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
vector<int> mod_dist(n, 1e9);
vector<int> dist(n, 1e9);
mod_dist[source] = dist[source] = 0;
pq.emplace(0, source);
fill(parent.begin(), parent.end(), -1);
parent[source] = -2;
while (!pq.empty()) {
int cost, node; tie(cost, node) = pq.top(); pq.pop();
if (cost != mod_dist[node]) continue;
for (auto &p : adj[node]) {
int x, cost; tie(x, cost) = p;
if (capacity[node][x] - flow[node][x] == 0) continue;
cost += real_dist[node] - real_dist[x];
if (mod_dist[x] > mod_dist[node] + cost) {
mod_dist[x] = mod_dist[node] + cost;
dist[x] = dist[node] + p.second;
pq.emplace(mod_dist[x], x);
parent[x] = node;
}
}
}
real_dist = move(dist);
return parent[sink] != -1;
}
void IncreaseFlow(int source, int sink, pair<int, int> &max_flow_min_cost,
vector<int> &parent, vector<int> &dist, vector<vector<int>> &flow,
vector<vector<int>> &capacity) {
int node = sink, added_flow = 1e9;
while (node != source) {
added_flow = min(added_flow,
capacity[parent[node]][node] - flow[parent[node]][node]);
node = parent[node];
}
max_flow_min_cost.first += added_flow;
max_flow_min_cost.second += added_flow * dist[sink];
node = sink;
while (node != source) {
flow[parent[node]][node] += added_flow;
flow[node][parent[node]] -= added_flow;
node = parent[node];
}
}
int main() {
ifstream cin("fmcm.in");
ofstream cout("fmcm.out");
int n, m, source, sink; cin >> n >> m >> source >> sink; --source, --sink;
vector<vector<pair<int, int>>> adj(n);
vector<vector<int>> flow(n, vector<int>(n));
vector<vector<int>> capacity(n, vector<int>(n));
while (m--) {
int u, v, cap, cost; cin >> u >> v >> cap >> cost; --u, --v;
adj[u].emplace_back(v, +cost);
adj[v].emplace_back(u, -cost);
capacity[u][v] += cap;
}
auto real_dist = BellmanFord(source, capacity, adj);
vector<int> parent(n);
pair<int, int> max_flow_min_cost = {0, 0};
while (CanIncreaseFlow(source, sink, parent, real_dist, adj, flow, capacity)) {
IncreaseFlow(source, sink, max_flow_min_cost, parent, real_dist, flow, capacity);
}
cout << max_flow_min_cost.second << endl;
}