#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")