#include <bits/stdc++.h>
#ifdef BLAT
#include "debug/debug.hpp"
#else
#define debug(x...)
#endif
using namespace std;
ifstream in ("fmcm.in");
ofstream out ("fmcm.out");
const int INF = 1e9;
class FlowGraph {
private:
struct Edge {
int from, to, cap, cost;
int nxt;
};
int n;
vector <int> graph, p, pi;
vector <Edge> edges;
public:
FlowGraph(int _n) : n(_n) {
graph.resize(_n, -1);
}
void addEdge(int from, int to, int cap, int cost) {
auto add = [&](int from, int to, int cap, int cost) {
edges.push_back(Edge{from, to, cap, cost, graph[from]});
graph[from] = edges.size() - 1;
};
add(from, to, cap, cost);
add(to, from, 0, -cost);
}
void bellmanFord(int s) {
vector <int> dist(n, INF);
dist[s] = 0;
p.assign(n, -1);
vector <bool> inqueue(n, false);
queue <int> q;
q.push(s);
while (!q.empty()) {
int from = q.front();
q.pop();
inqueue[from] = false;
for (int i = graph[from]; i != -1; i = edges[i].nxt) {
Edge e = edges[i];
if (e.cap && dist[e.to] > dist[e.from] + e.cost) {
dist[e.to] = dist[e.from] + e.cost;
p[e.to] = i;
if (!inqueue[e.to]) {
inqueue[e.to] = true;
q.push(e.to);
}
}
}
}
pi = dist;
}
bool dijkstra(int s, int t) {
vector <int> dist(n, INF); dist[s] = 0;
p.assign(n, -1);
priority_queue <pair <int, int>> pq;
pq.push(make_pair(0, s));
while (!pq.empty()) {
auto [d, from] = pq.top(); pq.pop();
if (d != -dist[from]) continue;
for (int i = graph[from]; i != -1; i = edges[i].nxt) {
Edge e = edges[i];
if (e.cap && dist[e.to] > dist[e.from] + pi[e.from] - pi[e.to] + e.cost) {
dist[e.to] = dist[e.from] + pi[e.from] - pi[e.to] + e.cost;
p[e.to] = i;
pq.push(make_pair(-dist[e.to], e.to));
}
}
}
for (int i = 0; i < n; i++)
pi[i] = min(pi[i] + dist[i], INF);
return p[t] != -1;
}
pair <int, int> minCostMaxFlow(int s, int t) {
int maxFlow = 0;
int minCost = 0;
bellmanFord(s);
while (dijkstra(s, t)) {
int flow = INF;
for (int edge = p[t]; edge != -1; edge = p[edges[edge].from])
flow = min(flow, edges[edge].cap);
// debug(flow);
for (int edge = p[t]; edge != -1; edge = p[edges[edge].from]) {
edges[edge].cap -= flow;
edges[edge ^ 1].cap += flow;
minCost += edges[edge].cost * flow;
}
maxFlow += flow;
}
return make_pair(minCost, maxFlow);
}
};
int main() {
int n, m, s, d;
in >> n >> m >> s >> d;
s--; d--;
FlowGraph graph(n);
for (int i = 0; i < m; i++) {
int from, to, cap, cost;
in >> from >> to >> cap >> cost;
from--; to--;
graph.addEdge(from, to, cap, cost);
}
out << graph.minCostMaxFlow(s, d).first << '\n';
return 0;
}