#include <iostream>
#include <cstring>
using namespace std;
const int N = 1001;
const int MAX = 1 << 30;
int dm[N][N];
int pm[N][N];
int minDis, minCost;
void dijkstra(int s, int t, int n);
int main(){
int n, m;
while(cin >> n >> m){
if(n==0 && m==0) break;
//初始化距离矩阵和费用矩阵
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
dm[i][j] = MAX;
pm[i][j] = MAX;
}
}
for(int i=0; i<m; i++){
int a, b, d, p;
cin >> a >> b >> d >> p;
//这两个判断条件是为了处理重边
if(dm[a][b] > d){
dm[a][b] = dm[b][a] = d;
pm[a][b] = pm[b][a] = p;
}
else if(dm[a][b]==d && pm[a][b]>p){
pm[a][b] = pm[b][a] = p;
}
}
int s, t;
cin >> s >> t;
dijkstra(s, t, n);
cout << minDis << ' ' << minCost << endl;
}
//system("pause");
return 0;
}
void dijkstra(int s, int t, int n){
//存储点s到各点的距离和费用
int dis[N];
int cost[N];
for(int i=1; i<=n; i++){
dis[i] = MAX;
cost[i] = MAX;
}
//用于判断是否已经求出s点到某点的最短距离和费用
bool visit[N];
memset(visit, false, sizeof(visit));
//点s到自己的距离和费用为0
dis[s] = 0;
cost[s] = 0;
for(int i=0; i<n; i++){
int min = MAX;
int k;
for(int j=1; j<=n; j++){
if(!visit[j] && dis[j]<min){
min = dis[j];
k = j;
}
}
visit[k] = true;
for(int j=1; j<=n; j++){
if(!visit[j] && dis[j]>min+dm[k][j]){
dis[j] = min + dm[k][j];
cost[j] = cost[k] + pm[k][j];
}
else if(!visit[j] && dis[j]==min+dm[k][j] && cost[j]>cost[k]+pm[k][j]){
cost[j] = cost[k] + pm[k][j];
}
}
}
minDis = dis[t];
minCost = cost[t];
}