#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;
}