#include<bits/stdc++.h>
using namespace std;
char buf[1<<20],*_=buf,*__=buf;
#define gc() (_==__&&(__=(_=buf)+fread(buf,1,1<<20,stdin),_==__)?EOF:*_++)
#define TT template<class T>inline
TT bool read(T &x){
x=0;char c=gc();bool f=0;
while(c<48||c>57){if(c==EOF)return 0;f^=(c=='-'),c=gc();}
while(47<c&&c<58)x=(x<<3)+(x<<1)+(c^48),c=gc();
if(f)x=-x;return 1;
}
TT bool read(T&a,T&b){return read(a)&&read(b);}
TT bool read(T&a,T&b,T&c){return read(a)&&read(b)&&read(c);}
typedef long long ll;
const ll MAXN=5008,mod=1e9+7,inf=0x3f3f3f3f;
struct Mcfm{
struct E{int y,nt;ll flow,cost;}e[MAXN*20];
int head[MAXN],cnt=1;
void add(int x,int y,ll flow,ll cost){//x->y
e[++cnt].y=y;
e[cnt].flow=flow;
e[cnt].cost=cost;
e[cnt].nt=head[x];head[x]=cnt;
}
int n,m,s,t;
int dis[MAXN],now[MAXN];
bool vis[MAXN];
deque<int>que;
bool spfa(){
for(int i=0;i<=n;++i)dis[i]=inf,now[i]=head[i];
que.emplace_back(s),dis[s]=0,vis[s]=1;
int x,y;
while(!que.empty()){
x=que.front(),que.pop_front();
vis[x]=0;
for(int i=head[x];i;i=e[i].nt){
y=e[i].y;
if(e[i].flow>0&&dis[y]>dis[x]+e[i].cost){
dis[y]=dis[x]+e[i].cost;
if(!vis[y]){
if(!que.empty()&&dis[y]<dis[que.front()])
que.emplace_front(y);
else que.emplace_back(y);
vis[y]=1;
}
}
}
}
return dis[t]!=inf;
}
ll mincost=0,maxflow=0;
ll dfs(int x,ll totflow){
if(x==t||totflow==0)return totflow;
vis[x]=1;
ll ansflow=0,flow;
for(int&i=now[x],y;i;i=e[i].nt){
y=e[i].y;
if(vis[y]||e[i].flow<=0||dis[x]+e[i].cost!=dis[y])continue;
flow=dfs(e[i].y,min(totflow,e[i].flow));
if(flow<=0)dis[y]=-1;
e[i].flow-=flow;
e[i^1].flow+=flow;
totflow-=flow;
ansflow+=flow;
mincost+=flow*e[i].cost;
if(!totflow)break;
}return vis[x]=0,ansflow;
}
void dinic(){
ll flow;
while(spfa())
while((flow=dfs(s,1ll<<50))>0)
maxflow+=flow;
}
}mcfm;
int main() {
read(mcfm.n,mcfm.m);read(mcfm.s,mcfm.t);
int x,y;ll f,c;
for(int i=0;i<mcfm.m;++i){
read(x,y);read(f,c);
mcfm.add(x,y,f,c);
mcfm.add(y,x,0,-c);
}
mcfm.dinic();
cout<<mcfm.maxflow<<" "<<mcfm.mincost<<endl;
return 0;
}
//dijkstra版,需要o2优化不然慢
struct Mcfm{
struct E{int y,nt;ll flow,cost;}e[MAXN];
int head[MAXN],cnt=1;
void add(int x,int y,ll flow,ll cost){//x->y
e[++cnt].y=y;
e[cnt].flow=flow;
e[cnt].cost=cost;
e[cnt].nt=head[x];head[x]=cnt;
}
int n,m,s,t;
ll dis[MAXN],h[MAXN];
bool vis[MAXN];
void spfa(){
for(int i=0;i<=n;++i)h[i]=inf;
queue<int>que;
que.emplace(s),h[s]=0,vis[s]=1;
int x,y;
while(!que.empty()){
x=que.front(),que.pop();
vis[x]=0;
for(int i=head[x];i;i=e[i].nt){
y=e[i].y;
if(e[i].flow>0&&h[y]>h[x]+e[i].cost){
h[y]=h[x]+e[i].cost;
if(!vis[y])que.emplace(y),vis[y]=1;
}
}
}
}
ll mincost,maxflow;
int prep[MAXN],pree[MAXN];
typedef pair<ll,int>pii;
priority_queue<pair<ll,int>>que;
void mcfm(){
mincost=maxflow=0;
spfa();
while(1){
for(int i=0;i<=n;++i)dis[i]=inf;
pree[s]=0,prep[s]=0,dis[s]=0;
while(!que.empty())que.pop();
que.emplace(0,s);
while(!que.empty()){
pii tmp=que.top();que.pop();
int x=tmp.second;
if(-tmp.first!=dis[x])continue;
for(int i=head[tmp.second],y;i;i=e[i].nt){
y=e[i].y;
ll len=e[i].cost+h[x]-h[y];
if(e[i].flow>0&&dis[y]>dis[x]+len){
dis[y]=dis[x]+len;
que.emplace(-dis[y],y);
pree[y]=i,prep[y]=x;
}
}
}
if(dis[t]==inf)break;
ll flow=inf;
for(int i=t;i^s;i=prep[i])flow=min(flow,e[pree[i]].flow);
for(int i=t;i^s;i=prep[i]){
e[pree[i]].flow-=flow;
e[pree[i]^1].flow+=flow;
}
maxflow+=flow;
mincost+=flow*(dis[t]+h[t]);
for(int i=0;i<=n;++i)h[i]=min(h[i]+dis[i],inf);
}
}
}mcfm;