#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
#include <climits>
#include <cstring>
using namespace std;
const int MAX=1001;
const int INF=INT_MAX;
struct Edge{
int to;
int length;
int cost;
Edge(int t, int l, int c):to(t),length(l),cost(c){}
};
struct Point{
int number;
int distance;
Point(int n, int d):number(n),distance(d){}
bool operator<(const Point& p)const{
return distance>p.distance;
}
};
vector<Edge> graph[MAX];
int dist[MAX];
int cost[MAX];
void Dijkstra(int s){
priority_queue<Point> myPriorityQueue;
dist[s]=0;
cost[s]=0;
myPriorityQueue.push(Point(s,dist[s]));
while(!myPriorityQueue.empty()){
int u=myPriorityQueue.top().number;
myPriorityQueue.pop();
for(int i=0;i< graph[u].size();i++){
int v=graph[u][i].to;
int d=graph[u][i].length;
int c=graph[u][i].cost;
if((dist[v]>dist[u]+d) || (dist[v]==dist[u]+d && cost[v]>cost[u]+c)){
dist[v]=dist[u]+d;
cost[v]=cost[u]+c;
myPriorityQueue.push(Point(v,dist[v]));
}
}
}
return;
}
int main(){
int n,m;
while(scanf("%d %d",&n,&m)!=EOF){
if(n==0 && m==0){
break;
}
memset(graph,0,sizeof(graph));
fill(dist,dist+n+1,INF);
fill(dist,dist+n+1,INF);
while(m--){
int a,b,d,p;
scanf("%d %d %d %d",&a,&b,&d,&p);
graph[a].push_back(Edge(b,d,p));
graph[b].push_back(Edge(a,d,p));
}
int s,t;
scanf("%d %d",&s,&t);
Dijkstra(s);
if(dist[s]==INF){
dist[s]=-1;
cost[s]=0;
}
printf("%d %d\n",dist[t],cost[t]);
}
return 0;
}