#include <cstdio>
#include <algorithm>
#include <cstring>
//思路 : 不断找最短路, 直到不能增广了则为最小费用最大流
using namespace std;
int n, m, s, t;
struct node{
int a, b, c, n, v;
}d[200001];
int h[10001];
int v[10001];//费用
int w[10001];//容量
int u[10001];
int que[100001];
int pre[10001];//前导边
int bian[100001];
int ans;
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch<'0'||ch>'9') if(ch == '-') f = -1;
x = ch - 48;
while(ch = getchar(), '0'<=ch&&ch<='9') x = x * 10 + ch - 48;
return x * f;
}
void cr(int cnt, int a, int b, int c, int v){
d[cnt].a = a; d[cnt].b = b; d[cnt].c = c; d[cnt].v = v; d[cnt].n = h[a];
h[a] = cnt;
}
int cmp(int i, int j){
return d[i].v<d[j].v;
}
void bfs(){
memset(w,0,sizeof(v));
memset(v,1,sizeof(v));
memset(pre,0,sizeof(pre));
w[s] = 1e9; v[s] = 0;
int x, y, i, b, c, va, a, j;
que[x = y = 1] = s;
while(x <= y){
a = que[x++];
u[a] = 0;
for(j = h[a]; j < h[a+1]; j++){
i = bian[j];//一条条排完序的边出来
b = d[i].b;
c = d[i].c;
va = d[i].v;
if(c>0 && v[a]+va<v[b]){//费用小才入队
v[b] = v[a] + va;
pre[b] = i;
w[b] = w[a]<c?w[a]:c;
if(!u[b]){//spfa加sfl优化, 如果不在队列中,如果比目前对头的费用小就放在队头,不然放队尾, 可以减少入队
//可以
u[b] = 1;
if(v[b]<v[que[x]] && x > 1) que[--x] = b;
else que[++y] = b;
}
}
}
}
for(i = pre[t]; i; i = pre[d[i].a]){
d[i].c -= w[t];
d[i^1].c += w[t];//正向边反向边更新
}
}
int main(){
int i, j, a, b, c, x, a1 = 0, k;
n = read(); m = read(); s = read(); t = read();
for(i = 1; i <= m; i++){
a = read(); b = read(); c = read(); x = read();
cr(j=i*2,a,b,c,x);
cr(j^1,b,a,0,-x);
}
for(k=i=1; i <= n; i++){//人为的边排序, 把每一条边放入bian[]中
for(j = h[i], h[i] = k; j; j = d[j].n){
bian[k++] = j;
}
}
h[n+1] = k;
for(i = 1; i <= n; i++){
if(h[i] < h[i+1]){
sort(bian+h[i],bian+h[i+1],cmp);
}
}
//权值小的边先出来,这样同一起点的边的终点可以不重复入队
while(1){
bfs();
if(w[t] > 0){
a1 += w[t];
ans += v[t] * w[t];
}
else break;
}
printf("%d %d", a1, ans);
return 0;
}