#include<bits/stdc++.h>
using namespace std;
const int P=1000000007;
struct nob{
int to,jump,val,cost;
}a[500000];
int n,m,s,t,tot=1,jump[500000]={0};
int len[10005],line[1000005];
bool judge[10005];
inline int read(){
int rem=0,f=1;
char cha=getchar();
while(cha>'9'||cha<'0'){
if(cha=='-'){
f=-1;
}
cha=getchar();
}
while(cha<='9'&&cha>='0'){
rem=rem*10+cha-'0';
cha=getchar();
}
return rem*f;
}
void add(int x,int y,int z,int d){
tot++;
a[tot].to=y;
a[tot].jump=jump[x];
jump[x]=tot;
a[tot].cost=d;
a[tot].val=z;
}
bool SPFA(){
int head=0,tail=1,pos;
memset(judge,0,sizeof(judge));
for (int i=1; i<=n; i++) len[i]=P;
len[s]=0;
judge[s]=1;
line[1]=s;
while (head!=tail){
head++;
if (head>1000000) head=1;
pos=line[head];
for (int i=jump[pos]; i; i=a[i].jump){
if (a[i].val && len[pos]+a[i].cost<len[a[i].to]){
len[a[i].to]=len[pos]+a[i].cost;
if (!judge[a[i].to]){
judge[a[i].to]=1;
tail++;
if (tail>1000000) tail=1;
line[tail]=a[i].to;
}
}
}
judge[pos]=0;
}
if (len[t]==P) return 0;
else return 1;
}
int vis[8000+10];
int cnt=0;
int dfs(int pos,int l){
if (pos==t) return l;
int used=0,w=0;
vis[pos]=cnt;
for (int i=jump[pos]; i; i=a[i].jump){
if (vis[a[i].to]!=cnt && len[a[i].to]==len[pos]+a[i].cost && a[i].val){
w=l-used;
int le=dfs(a[i].to,min(w,a[i].val));
a[i].val-=le;
a[i^1].val+=le;
used+=le;
if (used==l) return l;
}
}
return used;
}
int main(){
int maxn=0,ans=0;
n=read();m=read();s=read();t=read();
for (int i=1,x,y,z,d; i<=m; i++){
x=read();y=read();z=read();d=read();
add(x,y,z,d);
add(y,x,0,-d);
}
int p;
while (SPFA()){
++cnt;
p=dfs(s,P);
maxn+=p;
ans+=p*len[t];
}
printf("%d %d",maxn,ans);
return 0;
}