#include <bits/stdc++.h>
#include <iomanip>
 
using namespace std;
 
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef pair<LD, LD> PLDLD;
typedef vector<int> VI;
typedef vector<LL> VLL;
typedef vector<char> VB;
 
#define FOR(i,a,b) for(int i=(a);i<(int)(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define CLR(a) memset((a), 0 ,sizeof(a))
#define ALL(a) a.begin(),a.end()
 
const LD eps=1e-10;
const long long INFLL=(LL)(1e9)*(LL)(1e9);
const int INF=1e9;
 
template<class T>
void chmin(T& a, const T b)
{
	if(a>b)
		a=b;
}
template<class T>
void chmax(T& a, const T b)
{
	if(a<b)
		a=b;
}
 
const LL pow(const LL p, const LL q)
{
	LL t=1;
	for(int i=0;i<q;i++)
		t*=p;
	return t;
}

template <typename T>
struct has_iter
{
	private:
		template <typename U>
		static constexpr true_type check(typename U::iterator*);
		template <typename U>
		static constexpr false_type check(...);

	public:
		static constexpr bool value = decltype(check<T>(nullptr))::value;
};

template<typename T, typename U = typename T::iterator>
void print(const T& container)
{
		auto&& first=begin(container), last=end(container);
		auto&& back=prev(last);
		for(auto e=first; e!=last; e=next(e))
			cout<<*e<<" \n"[e==back];
}

extern void* enabler;
template<typename Head, typename enable_if<!has_iter<Head>::value>::type*& = enabler>
void print(const Head& head)
{
	cout<<head<<endl;
}

template<typename Head, typename... Tail>
void print(const Head& head, const Tail&... tail)
{
	cout<<head<<" ";
	print(tail...);
}

void io_speedup()
{
	cin.tie(0);
	ios::sync_with_stdio(false);
}

template<typename T>
istream& operator >> (istream& is, vector<T>& vec)
{
	for(T& x: vec) is >> x;
	return is;
}

template<typename T>
vector<T> read(int n)
{
	vector<T> t(n);
	cin>>t;
	return t;
}

template<typename T>
T read()
{
	T t;
	cin>>t;
	return t;
}

namespace flow
{
    
    using FLOW = long long;
    struct Edge
    {
        int to;
        FLOW cap;
        int rev;
    };
    class FlowNetwork
    {
        public:
            FlowNetwork(int n):graph(vector<vector<Edge>>(n)),iter(vector<int>(n)),level(vector<int>(n))
            {}
            void add_Edge(int from, int to, FLOW cap);
            FLOW dinic(int from, int to);

        private:
            vector<vector<Edge>> graph;
            vector<int> iter, level;
            FLOW dfs(int from, int to, FLOW cap);
            void bfs(int from);
    };
    void FlowNetwork::add_Edge(int from, int to, FLOW cap)
    {
        //cout<<from<<":"<<to<<" "<<cap<<endl;
        graph[from].push_back((Edge){to,cap,(int)graph[to].size()});
        graph[to].push_back((Edge){from,0,(int)graph[from].size()-1});
    }

    void FlowNetwork::bfs(int from)
    {
        fill(level.begin(),level.end(),-1);
        queue<int> que;
        level[from]=0;
        que.push(from);
        while(!que.empty())
        {
            int v=que.front();
            que.pop();
            for(int i=0;i<graph[v].size();i++)
            {
                Edge &e=graph[v][i];
                if(e.cap>0 && level[e.to]<0)
                {
                    level[e.to] = level[v]+1;
                    que.push(e.to);
                }
            }
        }
    }

    FLOW FlowNetwork::dfs(int from, int to, FLOW f)
    {
        if(from == to) return f;
        for(int &i=iter[from];i<graph[from].size();i++)
        {
            Edge &e=graph[from][i];
            if(e.cap > 0 && level[from] < level[e.to])
            {
                FLOW d = dfs(e.to, to, min(e.cap, f));
                if(d>0)
                {
                    e.cap -= d;
                    graph[e.to][e.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }
    FLOW FlowNetwork::dinic(int from, int to)
    {
        FLOW flow=0;
        while(1)
        {
            bfs(from);
            if(level[to]<0) return flow;
            fill(iter.begin(),iter.end(),0);
            FLOW f;
            while((f=dfs(from,to,INF))>0)
            {
                flow+=f;
            }
        }
    }
}

namespace Dij
{

    typedef int Dist;

    struct Edge;
    typedef vector<Edge> Edges;
    typedef vector<Edges> Graph;
    const int INF = 1e9;

    struct Edge
    {
        int to,from;
        Dist dist,cap;
        Edge(int to_,Dist dist_):to(to_),dist(dist_),from(0),cap(0)
        {}
        Edge(int to_,int from_, Dist dist_, Dist cap_):to(to_),dist(dist_),from(from_),cap(cap_)
        {}
        bool operator >(const Edge &ed)const
        {
            return dist > ed.dist;
        }
    };

    //Shortest cost from i to j.
    Graph dijkstra(int i, const Graph &vertex)
    {
        vector<Dist> shortest(vertex.size(), INF);
        priority_queue<Edge, vector<Edge>, greater<Edge> > que;

        que.push(Edge(i, 0));
        shortest[i]=0;

        Edge state(0,0), tmp(0,0), e(0,0);
        while(!que.empty())
        {
            state = que.top();
            que.pop();
            if(shortest[state.to] < state.dist) continue;
            for(Edge e : vertex[state.to])
            {
                if(shortest[e.to] > shortest[state.to] + e.dist)
                {
                    shortest[e.to] = shortest[state.to] + e.dist;
                    tmp = Edge(e.to, shortest[e.to]);
                    que.push(tmp);
                }
            }
        }

        Graph newg(vertex.size());
        REP(i, vertex.size())
        {
            for(Edge e : vertex[i])
            {
                if(shortest[e.to] == shortest[i] + e.dist)
                    newg[i].push_back(e);
            }
        }
        return newg;
    }

}

int main()
{
    int n,m,s,t;
    cin>>n>>m>>s>>t;
    s--;
    t--;
    Dij::Graph g(n);
    REP(i,m)
    {
        int u,v,d,c;
        cin>>u>>v>>d>>c;
        u--;
        v--;
        g[u].push_back(Dij::Edge(v,u,d,c));
    }
    //print("dij");
    auto dag = dijkstra(s, g);
    flow::FlowNetwork fl(n);
    for(auto&& es:dag)
        for(auto&& e:es)
        {
            //print(e.from, e.to, e.cap);
            fl.add_Edge(e.from, e.to, e.cap);
        }
    //print("fl");;
    print(fl.dinic(s,t));
}



Measured memory_bytes: 3280