#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int N = 1010, INF = 0x3f3f3f3f;
int n, m;
int dis[N],cost[N], path[N];
struct Edge{
int to;
int len;
int cos;
};
struct Point{
int index;
int weight;
Point(int i, int w): index(i), weight(w){}
};
bool operator < (Point a, Point b)
{
return a.weight < b.weight;
}
vector<Edge> e[N];
void init(int n)
{
for(int i = 0; i <= n; i++)
{
dis[i] = INF;
cost[i] = INF;
path[i] = 0;
e[i].clear();
}
}
void dijkstra(int start)
{
priority_queue<Point> q;
dis[start] = 0;
cost[start] = 0;
q.push(Point(start, dis[start]));
while(!q.empty())
{
int p = q.top().index;
q.pop();
for(int i = 0; i < e[p].size(); i++)
{
int to = e[p][i].to;
int len = e[p][i].len;
int cos = e[p][i].cos;
if(dis[to] > dis[p] + len || (dis[to] == dis[p] + len && cost[to] > cost[p] + cos))
{
dis[to] = dis[p] + len;
cost[to] = cost[p] + cos;
q.push(Point(to, dis[to]));
path[to] = p;
}
}
}
}
int main() {
while(cin >> n >> m && n && m)
{
int a, b, d, p;
Edge cur;
init(n);
for(int i = 0; i < m; i++)
{
cin >> a >> b >> d >> p;
cur.to = b;
cur.len = d;
cur.cos = p;
e[a].push_back(cur);
cur.to = a;
e[b].push_back(cur);
}
int s, t;
cin >> s >> t;
dijkstra(s);
cout << dis[t] << " " << cost[t] << endl;
}
}
// 64 位输出请用 printf("%lld")