#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; }