#include <bits/stdc++.h>
using namespace std;
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
class Graph {
private:
int n, s, t;
vector<vector<int>> ad, cap, cst;
vector<int> pot, dst;
void bellman() {
fill(pot.begin(), pot.end(), 1e9);
pot[s] = 0;
vector<bool> inQueue(n + 1);
inQueue[s] = true;
queue<int> q; q.push(s);
while (!q.empty()) {
int node = q.front(); q.pop();
inQueue[node] = false;
for (int nghb : ad[node])
if (cap[node][nghb] && pot[node] + cst[node][nghb] < pot[nghb]) {
pot[nghb] = pot[node] + cst[node][nghb];
if (!inQueue[nghb]) {
q.push(nghb);
inQueue[nghb] = true;
}
}
}
}
bool dijkstra(vector<int>& dp, vector<int>& father) {
fill(dp.begin(), dp.end(), 1e9);
dp[s] = dst[s] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.emplace(0, s);
vector<bool> vis(n + 1);
while (!pq.empty()) {
int node = pq.top().second; pq.pop();
if (node != t && !vis[node]) {
vis[node] = true;
for (int nghb : ad[node])
if (cap[node][nghb] && dp[node] + cst[node][nghb] + pot[node] - pot[nghb] < dp[nghb]) {
dp[nghb] = dp[node] + cst[node][nghb] + pot[node] - pot[nghb];
father[nghb] = node;
dst[nghb] = dst[node] + cst[node][nghb];
pq.emplace(dp[nghb], nghb);
}
}
}
pot = dst;
return dp[t] != 1e9;
}
public:
Graph(int n, int s, int t) :
n(n), s(s), t(t), ad(n + 1),
cap(n + 1, vector<int>(n + 1)),
cst(n + 1, vector<int>(n + 1)),
pot(n + 1), dst(n + 1) { }
void addEdge(int x, int y, int z, int t) {
ad[x].push_back(y);
ad[y].push_back(x);
cap[x][y] = z;
cst[x][y] = +t;
cst[y][x] = -t;
}
int minCostMaxFlow() {
int cost = 0;
vector<int> dp(n + 1);
vector<int> father(n + 1);
bellman();
while (dijkstra(dp, father)) {
int flow = 1e9;
for (int i = t; i != s; i = father[i])
flow = min(flow, cap[father[i]][i]);
for (int i = t; i != s; i = father[i]) {
cost += flow * cst[father[i]][i];
cap[father[i]][i] -= flow;
cap[i][father[i]] += flow;
}
}
return cost;
}
};
int main() {
int n, m, s, t; fin >> n >> m >> s >> t;
Graph graph(n, s, t);
for (int i = 0; i < m; i++) {
int x, y, z, t; fin >> x >> y >> z >> t;
graph.addEdge(x, y, z, t);
}
fout << graph.minCostMaxFlow() << '\n';
fout.close();
return 0;
}