#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <cstring>
#include <chrono>
#include <cassert>
#include <bitset>
#include <stack>
#include <queue>
#include <iomanip>
#include <random>
#include <string>
#include <complex>
#include <algorithm>
#include <numeric>
#include <immintrin.h>
#ifdef _MSC_VER
# include <intrin.h>
# define __builtin_popcount __popcnt
# define __builtin_popcountll __popcnt64
#endif
#pragma warning(disable : 4996)
//#pragma GCC optimize("Ofast")
#define x first
#define y second
#define ld long double
#define ll long long
#define ull unsigned long long
#define us unsigned short
#define lsb(x) ((x) & (-(x)))
#define pii pair <int, int>
#define pll pair <ll, ll>
using namespace std;
//const int MOD = (int)1e9 + 7;
mt19937_64 gen(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count());
uniform_int_distribution <int> rng;
const ld PI = acos(-1);
const int MOD = (int)1e9 + 7;
struct Edge {
int to, cap, ind, cost;
};
class MaxFlow {
public:
vector <vector <Edge>> g;
vector <int> dist;
vector <int> lst;
void init(int n) {
g.resize(n + 1);
dist.resize(n + 1);
lst.resize(n + 1);
}
void add_edge(int x, int y, int cap, int cost) {
g[x].push_back({ y, cap, (int)g[y].size(), cost });
g[y].push_back({ x, 0, (int)g[x].size() - 1, -cost });
}
int bfs(int src, int dst) {
queue <int> q;
fill(dist.begin(), dist.end(), (int)1e9);
fill(lst.begin(), lst.end(), 0);
dist[src] = 0;
q.push(src);
while (!q.empty()) {
int node = q.front();
q.pop();
for (auto& [son, cap, ind, cost] : g[node]) {
if (cap > 0 && dist[son] > cost + dist[node]) {
dist[son] = cost + dist[node];
lst[son] = ind;
q.push(son);
}
}
}
if (dist[dst] == (int)1e9)
return 0;
return dist[dst];
}
pii min_cost_max_flow(int src, int dst) {
int cost, max_flow = 0, min_cost = 0;
while (cost = bfs(src, dst)) {
int flow = (int)1e9, node = dst;
while (node != src) {
int prev_node = g[node][lst[node]].to;
flow = min(flow, g[prev_node][g[node][lst[node]].ind].cap);
node = prev_node;
}
node = dst;
while (node != src) {
int prev_node = g[node][lst[node]].to;
g[prev_node][g[node][lst[node]].ind].cap -= flow;
g[node][lst[node]].cap += flow;
node = prev_node;
}
max_flow += flow;
min_cost += flow * cost;
}
return { max_flow, min_cost };
}
} network;
void solve(int test = 0) {
int n, m, src, dst;
cin >> n >> m >> src >> dst;
network.init(n);
for (; m; m--) {
int x, y, z, c;
cin >> x >> y >> z >> c;
network.add_edge(x, y, z, c);
}
cout << network.min_cost_max_flow(src, dst).y << "\n";
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
srand(time(0));
#ifdef LOCAL
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#else
freopen("fmcm.in", "r", stdin);
freopen("fmcm.out", "w", stdout);
#endif
int T = 1;
//cin >> T;
for (int t = 1; t <= T; t++) {
solve(t);
}
return 0;
}