//依然有点懵
#include <iostream>
#include <climits>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const int INF=INT_MAX;
struct Point
{
int id;
int distance;
bool operator<(const Point& p)const//放到优先队列里的元素自动排序
{
return distance>p.distance;
}
Point(int i,int d)
{
id=i;
distance=d;
}
};
struct Edge
{
int to;
int distance;
int cost;
Edge(int t,int d,int c)
{
to=t;
distance=d;
cost=c;
}
};
vector<Edge> graph[1001];//向量类似高级数组,每个点里存它的所有Edge
int dis[1001];
int cost[1001];
void Dijkstra(int s)
{
priority_queue<Point> q;
dis[s]=0;
cost[s]=0;
q.push(Point(s,0));
while(!q.empty())
{
int u=q.top().id;
q.pop();
for(int i=0;i<graph[u].size();i++)//每个点都是自己vector数组从最先的位置(0)开始存
{
int v=graph[u][i].to;
int d=graph[u][i].distance;
int c=graph[u][i].cost;
if(dis[u]+d<dis[v]||((dis[u]+d==dis[v])&&(cost[u]+c<cost[v])))
{
dis[v]=dis[u]+d;
cost[v]=cost[u]+c;
q.push(Point(v,dis[v]));
}
}
}
}
int main() {
int n,m;
while (cin >> n>>m) {
if(n==0&&m==0)break;
memset(graph,0,sizeof(graph));
fill(dis,dis+1001,INF);
fill(cost,cost+1001,INF);
for(int i=1;i<=m;i++)
{
int from,to,d,c;
cin>>from>>to>>d>>c;
graph[from].push_back(Edge(to,d,c));//??每个点可能有多条连线啊
graph[to].push_back(Edge(from,d,c));
}
int s,t;
cin>>s>>t;
Dijkstra(s);
cout<<dis[t]<<" "<<cost[t]<<endl;
}
}