#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define N 1010
struct Edge {
int y;
int weight;
int spend;
};
struct Node {
int x;//源点到该点的距离
int dist;//路径长度
int money;//到该节点花费
};
bool operator<(Node l, Node r) {
if (l.dist == r.dist) {
return l.money > r.money;
}
return l.dist > r.dist;
}
vector<Edge> v[N];
void Dijikstra(int s, int t, int n) {
int Dist[N];
int Money[N];
bool isvisit[N];
for (int i = 0; i < N; i++) {
Dist[i] = INT32_MAX;
Money[i] = INT32_MAX;
isvisit[i] = false;
}//初始化结束
Dist[s] = 0;
Money[s] = 0;
priority_queue<Node> pqueue;
Node node;
node.x = s;
node.dist = Dist[s];
node.money = Money[s];
pqueue.push(node);
while ((pqueue.empty() == false)) {
int cur = pqueue.top().x;
pqueue.pop();
if (isvisit[cur] == true) {
continue;
}
isvisit[cur] = true;
//找到他的邻居
for (int i = 0; i < v[cur].size(); i++) {
int x = v[cur][i].y;
int weight = v[cur][i].weight;
int spend = v[cur][i].spend;
if (Dist[x] > Dist[cur] + weight) {
Dist[x] = Dist[cur] + weight;
Money[x] = Money[cur] + spend;
Node node;
node.money = Money[x];
node.dist = Dist[x]; //更新源点到该点的距离
node.x = x;
pqueue.push(node);
} else if (Dist[x] == Dist[cur] + weight) {
if (Money[x] > Money[cur] + spend) {
Money[x] = Money[cur] + spend;
Node node;
node.money = Money[x];
node.dist = Dist[x]; //更新源点到该点的距离
node.x = x;
pqueue.push(node);
}
}
}
}
printf("%d %d", Dist[t], Money[t]);
}
int main() {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
if (n == 0 && m == 0) {
break;
}
//更新边
for (int i = 0; i < n; i++) {
v[i].clear();
}
for (int i = 0; i < m; i++) {
int s1, s2, s3, s4;
scanf("%d%d%d%d", &s1, &s2, &s3, &s4);
Edge e;
e.y = s2;
e.weight = s3;
e.spend = s4;
v[s1].push_back(e);
e.y = s1;
v[s2].push_back(e);
}
int s, t;
scanf("%d%d", &s, &t);
Dijikstra(s, t, n);
}
return 0;
}