#include<stdio.h>
#define MAXN (int)1e5+7
int m, n, s, d;
typedef struct edge {
int to;//终点
int next;//下一条边
int s;//路长
int m;//money
}edge;
typedef struct pii
{
int s;//路长
int m;//费用
}pii;
edge edges[MAXN];
int cnt, head[MAXN];//head[i]为编号为i的城市所能到达的所有地区
short vis[MAXN];//蓝白点
pii dist[MAXN];
inline short blean(pii a, pii b);//a比b更符合要求
inline void add(int from, int to, int s, int m);//从哪里来,要到哪里去,边权多少
void dijkstra(int start);
void newdij(int start);
int main() {
for (int i = 0; i < MAXN; ++i) {
dist[i].m = 0xfffff;
dist[i].s = 0xfffff;
}
scanf("%d%d%d%d", &n, &m, &s, &d);
s++; d++;
for (int i = 1; i <= m; ++i) {
int a, b, s, m;
scanf("%d%d%d%d", &a, &b, &s, &m);
a++; b++;
add(a, b, s, m);
add(b, a, s, m);
}
dist[s].m = 0;
dist[s].s = 0;
dijkstra(s);
printf("%d %d\n", dist[d].s, dist[d].m);
return 0;
}
inline void add(int from, int to, int s, int m) {
++cnt;//新建一条边
edges[cnt].s = s;//边权
edges[cnt].m = m;
edges[cnt].to = to;
edges[cnt].next = head[from];//向前加边
head[from] = cnt;
}
short blean(pii a, pii b) {
if (a.s == b.s)return a.m < b.m;
return a.s < b.s;
}
void dijkstra(int start) {
if (start == -1)return;
vis[start] = 1;
for (int e = head[start]; e; e = edges[e].next) {
pii temp = dist[start];
temp.s += edges[e].s;
temp.m += edges[e].m;
if (blean(temp, dist[edges[e].to])) {
dist[edges[e].to] = temp;
}
}
pii min = { 0xfffff,0xfffff };
int mark = -1;
for (int i = 1; i <= n + 1; ++i) {
if (!vis[i] && blean(dist[i], min)) {
min = dist[i];
mark = i;
}
}
dijkstra(mark);
}
void newdij(int start) {
while (1) {
int mark = -1;
pii min = { 0xfffff,0xfffff };
for (int i = 1; i <= n + 1; ++i) {
if (!vis[i] && blean(dist[i], min)) {
min = dist[i];
mark = i;
}
}
if (mark == -1)break;
vis[mark] = 1;
for (int e = head[mark]; e; e = edges[e].next) {
pii tmp = { dist[mark].s + edges[e].s,dist[mark].m + edges[mark].m };
if (blean(tmp, dist[edges[e].to])) {
dist[edges[e].to] = tmp;
}
}
}
}
#define MAXN (int)1e5+7
int m, n, s, d;
typedef struct edge {
int to;//终点
int next;//下一条边
int s;//路长
int m;//money
}edge;
typedef struct pii
{
int s;//路长
int m;//费用
}pii;
edge edges[MAXN];
int cnt, head[MAXN];//head[i]为编号为i的城市所能到达的所有地区
short vis[MAXN];//蓝白点
pii dist[MAXN];
inline short blean(pii a, pii b);//a比b更符合要求
inline void add(int from, int to, int s, int m);//从哪里来,要到哪里去,边权多少
void dijkstra(int start);
void newdij(int start);
int main() {
for (int i = 0; i < MAXN; ++i) {
dist[i].m = 0xfffff;
dist[i].s = 0xfffff;
}
scanf("%d%d%d%d", &n, &m, &s, &d);
s++; d++;
for (int i = 1; i <= m; ++i) {
int a, b, s, m;
scanf("%d%d%d%d", &a, &b, &s, &m);
a++; b++;
add(a, b, s, m);
add(b, a, s, m);
}
dist[s].m = 0;
dist[s].s = 0;
dijkstra(s);
printf("%d %d\n", dist[d].s, dist[d].m);
return 0;
}
inline void add(int from, int to, int s, int m) {
++cnt;//新建一条边
edges[cnt].s = s;//边权
edges[cnt].m = m;
edges[cnt].to = to;
edges[cnt].next = head[from];//向前加边
head[from] = cnt;
}
short blean(pii a, pii b) {
if (a.s == b.s)return a.m < b.m;
return a.s < b.s;
}
void dijkstra(int start) {
if (start == -1)return;
vis[start] = 1;
for (int e = head[start]; e; e = edges[e].next) {
pii temp = dist[start];
temp.s += edges[e].s;
temp.m += edges[e].m;
if (blean(temp, dist[edges[e].to])) {
dist[edges[e].to] = temp;
}
}
pii min = { 0xfffff,0xfffff };
int mark = -1;
for (int i = 1; i <= n + 1; ++i) {
if (!vis[i] && blean(dist[i], min)) {
min = dist[i];
mark = i;
}
}
dijkstra(mark);
}
void newdij(int start) {
while (1) {
int mark = -1;
pii min = { 0xfffff,0xfffff };
for (int i = 1; i <= n + 1; ++i) {
if (!vis[i] && blean(dist[i], min)) {
min = dist[i];
mark = i;
}
}
if (mark == -1)break;
vis[mark] = 1;
for (int e = head[mark]; e; e = edges[e].next) {
pii tmp = { dist[mark].s + edges[e].s,dist[mark].m + edges[mark].m };
if (blean(tmp, dist[edges[e].to])) {
dist[edges[e].to] = tmp;
}
}
}
}