#include <bits/stdc++.h>
      
#define FOR(i,a,b) for( ll i = (a); i < (ll)(b); i++ )
#define REP(i,n) FOR(i,0,n)
#define YYS(x,arr) for(auto& x:arr)
#define ALL(x) (x).begin(),(x).end()
#define SORT(x) sort( (x).begin(),(x).end() )
#define REVERSE(x) reverse( (x).begin(),(x).end() )
#define UNIQUE(x) (x).erase( unique( ALL( (x) ) ) , (x).end() )
#define PW(x) (1LL<<(x))
#define SZ(x) ((ll)(x).size())
#define SHOW(x) cout << #x << " = " << x << endl
#define SHOWA(x,n) for( int yui = 0; yui < n; yui++ ){ cout << x[yui] << " "; } cout << endl

#define pb emplace_back
#define fi first
#define se second

using namespace std;

typedef long double ld;
typedef long long int ll;
typedef pair<int,int> pi;
typedef pair<ll,ll> pl;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<bool> vb;
typedef vector<ld> vd;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<vpl> gr;
typedef vector<vl> ml;
typedef vector<vd> md;
typedef vector<vi> mi;
     
const ll INF = (ll)1e9 + 10;
const ll INFLL = (ll)1e18 + 10;
const ld EPS = 1e-12;
const ll MOD = 1e9+7;
     
template<class T> T &chmin( T &a , const T &b ){ return a = min(a,b); }
template<class T> T &chmax( T &a , const T &b ){ return a = max(a,b); }
template<class T> inline T sq( T a ){ return a * a; }

ll in(){ long long int x; scanf( "%lld" , &x ); return x; }
char yuyushiki[1000010]; string stin(){ scanf( "%s" , yuyushiki ); return yuyushiki; }

// head

struct MaxFlow{
  typedef ll weight;
  const weight zero = 0;
  const weight INF_WEIGHT = INFLL;
  struct edge{
    int to, rev;
    weight cap;
    edge(){}
    edge( int to , weight cap , int rev ) : to(to) , cap(cap) , rev(rev) {}
  };
  vector<vector<edge> > G;
  vi level, iter;
  int n;
  void init( int arg_n ){
    n = arg_n;
    G = vector<vector<edge> >( n , vector<edge>(0) );
  }
  void add_edge( int from , int to , weight cap ){
    G[from].pb( to , cap , SZ(G[to]) );
    G[to].pb( from , zero , SZ(G[from])-1 );
  }
  void bfs( int s ){
    level = vi( n , -1 );
    queue<int> que;
    level[s] = 0;
    que.push( s );
    while( !que.empty() ){
      int v = que.front(); que.pop();
      YYS( e , G[v] ){
	if( e.cap > zero && level[e.to] < 0 ){
	  level[e.to] = level[v] + 1;
	  que.push( e.to );
	}
      }
    }
  }
  weight dfs( int v , int t , weight f ){
    if( v == t ) return f;
    for( int &i = iter[v]; i < G[v].size(); i++ ){
      edge &e = G[v][i];
      if( e.cap > zero && level[v] + 1 == level[e.to] ){
	weight d = dfs( e.to , t , min( f , e.cap ) );
	if( d > zero ){
	  e.cap -= d;
	  G[e.to][e.rev].cap += d;
	  return d;
	}
      }
    }
    return zero;
  }
  weight max_flow( int s , int t ){
    weight flow = zero;
    while( 1 ){
      bfs( s );
      if( level[t] < 0 ) return flow;
      iter = vi( n , 0 );
      weight f;
      while( (f = dfs( s , t , INF_WEIGHT )) > zero ) flow += f;
    }
  }
};

using E = tuple<int, int, int>;

int n, m, s, t;

vector<E> edges;

vector<E> G[210];
vi U[210];

int dist[210];

MaxFlow mf;

void dijkstra(){
  REP( i , n ){
    dist[i] = INF;
  }
  dist[s] = 0;
  priority_queue<pi, vpi, greater<pi> > que;
  que.emplace(0, s);
  while(!que.empty()){
    int p, d;
    d = que.top().fi;
    p = que.top().se;
    que.pop();
    if(dist[p] != d){
      continue;
    }
    YYS(w, G[p]){
      int to, di, id;
      tie(to, di, id) = w;
      int nd = d + di;
      if(dist[to] > nd){
        dist[to] = nd;
        que.emplace(nd, to);
        U[to].clear();
        U[to].pb(id);
      } else if(dist[to] == nd){
        U[to].pb(id);
      }
    }
  }
}

string WeightedGraphVisualizer(vector<vector<tuple<ll, ll>>> G, bool directed=false){
  /*
    
   */
  stringstream ss;
  if(directed){
    ss << "digraph G {" << endl;
  } else {
    ss << "graph G {" << endl;
  }
  int n_node = G.size();
  for(int i = 0; i < n_node; i++){
    for(auto &e : G[i]){
      ll to, co;
      tie(to, co) = e;
      if(!directed && i > to){
        continue;
      }
      ss << "  "; // indent
      if(directed){
        ss << i << " -> " << to;
      } else {
        ss << i << " -- " << to;
      }
      ss << " [ label = " << co << " ];" << endl;
    }
  }
  ss << "}" << endl;
  return ss.str();
}



int main(){

  
  n = in();
  m = in();
  s = in() - 1;
  t = in() - 1;
  // vector<vector<tuple<ll, ll>>> gg(n);
  REP( i , m ){
    int a = in() - 1;
    int b = in() - 1;
    int d = in();
    int c = in();
    G[a].pb(b, d, i);
    edges.pb(a, b, c);
  }

  dijkstra();

  mf.init(n);
  REP( i , n ){
    YYS(w, U[i]){
      int a, b, co;
      tie(a, b, co) = edges[w];
      /*
      cout << a << " " << b << " " << co << endl;
      gg[a].pb(b, co);
      gg[b].pb(a, co);
      */
      mf.add_edge(a, b, co);
    }
  }

  /*
  cout << WeightedGraphVisualizer(gg) << endl;
  return 0;
  */

  
  cout << mf.max_flow(s, t) << endl;
  
  return 0;
}



Measured memory_bytes: 3340