#include<iostream>
using namespace std;
const int N = 5e3 + 10;
const int M = 5e4 + 10;
const int INF = (int)0x3f3f3f3f3f3f3f3f;
struct Edge {
int v, w, c;
int next;
} pool[2 * M];
int ne = 1, head[N];
void addEdge(int u, int v, int w, int c) {
pool[++ne] = {v, w, c, head[u]};
head[u] = ne;
}
int n, m, s, t;
namespace dinic {
int dis[N], dep[N], vis[N], now[N];
int que[M], hd, tl;
int ans;
bool spfa() {
for(int i = 1; i <= n; i++) {
vis[i] = 0;
dis[i] = INF;
now[i] = head[i];
}
hd = 1, tl = 0;
que[++tl] = s;
dis[s] = 0;
while(hd <= tl) {
int u = que[hd++];
vis[u] = 0;
for(int i = head[u]; i; i = pool[i].next) {
int v = pool[i].v, w = pool[i].w, c = pool[i].c;
if(w && dis[u] + c < dis[v]) {
dis[v] = dis[u] + c;
dep[v] = dep[u] + 1;
if(vis[v]) continue;
vis[v] = 1;
que[++tl] = v;
}
}
}
return dis[t] != INF;
}
int dfs(int u, int sum, int cost) {
if(u == t) {
ans += sum * cost;
return sum;
}
int flow = 0;
for(int i = now[u]; i && sum; i = pool[i].next) {
int v = pool[i].v, w = pool[i].w, c = pool[i].c;
now[u] = i;
if(!w || dep[v] != dep[u] + 1 || dis[v] != dis[u] + c || vis[v]) continue;
int k = dfs(v, min(sum, w), cost + c);
if(!k) dis[v] = 0;
else {
pool[i].w -= k;
pool[i ^ 1].w += k;
sum -= k;
flow += k;
}
}
return flow;
}
void calc() {
int flow = 0;
while(spfa()) flow += dfs(s, INF, 0);
cout << flow << ' ' << ans << endl;
}
}
int main() {
cin >> n >> m >> s >> t;
for(int i = 1; i <= m; i++) {
int u, v, w, c;
cin >> u >> v >> w >> c;
addEdge(u, v, w, c);
addEdge(v, u, 0, -c);
}
dinic::calc();
return 0;
}