#include <bits/stdc++.h>
#define NMAX (int)(4e3+4)
#define MMAX (int)(3e4+4)
#define pb emplace_back
#define ft first
#define sd second
using namespace std;
ifstream fin("fmcm.in");
ofstream fout("fmcm.out");
typedef pair <int, int> pairINT;
typedef long long ll;
struct edge{
int x,y,cap,cost,flow;
edge(int a,int b,int c,int d){
x=a;
y=b;
cap=c;
cost=d;
flow=0;
}
edge(){
}
};
class Network{
public:
int n;
void add_edge(int x,int y,int cap,int cost){
g[x].pb(++id);
e[id]=edge(x, y, cap, cost);
g[y].pb(++id);
e[id]=edge(y, x, 0, -cost);
}
int GetFlow(int s, int d){
int add,sol;
bellman_ford(s);
while(dijkstra(s, d)){
add=1e9;
for(int node=d;tata[node];node=e[tata[node]].x)
add=min(add, e[tata[node]].cap - e[tata[node]].flow);
for(int node=d;tata[node];node=e[tata[node]].x){
e[tata[node]].flow+=add;
e[tata[node]^1].flow-=add;
sol+=add*e[tata[node]].cost;
}
}
return sol;
}
private:
bool dijkstra(int node, int fin){
memset(cost, 0x3f, sizeof cost);
tata[fin]=0;
set <pairINT> pq;
int temp;
cost[node]=0;
pq.insert({0, node});
while(!pq.empty()){
node=(*pq.begin()).sd;
temp=(*pq.begin()).ft;
pq.erase(pq.begin());
if(temp > cost[node]) continue;
for(auto it:g[node]){
temp=cost[node] + dist[node] + e[it].cost - dist[e[it].y];
if(e[it].flow != e[it].cap && cost[e[it].y] > temp){
cost[e[it].y]=temp;
tata[e[it].y]=it;
pq.insert({cost[e[it].y], e[it].y});
}
}
}
for(int i=1;i<=n;++i)
dist[i]+=cost[i];
return tata[fin];
}
void bellman_ford(int node){
set <pairINT> pq;
bitset <NMAX> inQue;
memset(dist, 0x3f, sizeof dist);
inQue.reset();
dist[node]=0;
pq.insert({0, node});
while(!pq.empty()){
node=(*pq.begin()).sd;
pq.erase(pq.begin());
inQue[node]=0;
for(auto it:g[node]){
if(e[it].cap && dist[e[it].y] > dist[node] + e[it].cost){
dist[e[it].y]=dist[node] + e[it].cost;
if(!inQue[e[it].y])
pq.insert({dist[e[it].y], e[it].y});
inQue[e[it].y]=1;
}
}
}
}
int id=1;
int dist[NMAX],tata[NMAX],cost[NMAX];
vector <int> g[NMAX];
edge e[MMAX];
};
Network G;
int main(){
int n,m,s,t;
fin>>n>>m>>s>>t;
G.n = n;
for(int i=0,x,y,c,k;i<m;++i){
fin>>x>>y>>c>>k;
G.add_edge(x,y,c,k);
}
fout<<G.GetFlow(s, t);
return 0;
}