#include <fstream>
#include <vector>
#include <queue>
//12:28
using namespace std;
const int NMAX = 350 + 5;
const int MMAX = 12500 + 5;
const int INF = 1E9;
int N, M, S, T;
int cap[NMAX][NMAX];
int cost[NMAX][NMAX];
vector <int> graph[NMAX];
bool inQueue[NMAX];
queue <int> q;
int p[NMAX];
int father[NMAX];
void BF() {
for (int i = 1; i <= N; ++ i)
p[i] = INF, father[i] = inQueue[i] = 0;
q.push(S);
p[S] = 0;
inQueue[S] = true;
while (!q.empty()) {
int node = q.front();
q.pop();
inQueue[node] = false;
for (auto it: graph[node])
if (cap[node][it] && p[node] + cost[node][it] < p[it]) {
p[it] = p[node] + cost[node][it];
father[it] = node;
if (!inQueue[it]) {
inQueue[it] = true;
q.push(it);
}
}
}
}
priority_queue <pair <int, int> > pq;
int dist[NMAX];
bool vis[NMAX];
bool dijkstra() {
for (int i = 1; i <= N; ++ i)
dist[i] = INF, vis[i] = false;
dist[S] = 0;
pq.push(make_pair(0, S));
while (!pq.empty()) {
int node = pq.top().second;
pq.pop();
if (vis[node])
continue;
vis[node] = true;
for (auto it: graph[node])
if (!vis[it] && cap[node][it] && dist[node] + cost[node][it] + p[node] - p[it] < dist[it]) { //Add p
dist[it] = dist[node] + cost[node][it] + p[node] - p[it];
father[it] = node;
pq.push(make_pair(-dist[it], it));
}
}
for (int i = 1; i <= N; ++ i)
p[i] = dist[i] - (p[S] - p[i]);
return vis[T];
}
int minCostFlow() {
int ans = 0;
BF();
while (dijkstra()) {
int node = T;
int f = INF;
while (node != S) {
f = min(f, cap[father[node]][node]);
node = father[node];
}
node = T;
while (node != S) {
cap[father[node]][node] -= f;
cap[node][father[node]] += f;
ans += cost[father[node]][node] * f;
node = father[node];
}
}
return ans;
}
int main()
{
ifstream cin("fmcm.in");
ofstream cout("fmcm.out");
cin >> N >> M >> S >> T;
for (int i = 1; i <= M; ++ i) {
int a, b, c, d;
cin >> a >> b >> c >> d;
cap[a][b] += c;
cost[a][b] += d;
cost[b][a] -= d;
graph[a].push_back(b);
graph[b].push_back(a);
}
cout << minCostFlow() << '\n';
return 0;
}