#include <cstring> #include <climits> #include <iostream> #include <queue> #include <vector> using namespace std; const int N = 1002; struct Edge { int to; //终点 int length; //长度 int weight; //权重 Edge(int t, int l, int w): to(t), length(l), weight(w) {} }; vector<Edge> graph[N]; 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; } }; int dis[N]; //记录原点到每个顶点的最短距离 int cost[N]; //花费 void Dijkstra(int s) { priority_queue<Point> pq; dis[s] = 0; cost[s] = 0; pq.push(Point(s, dis[s])); while (!pq.empty()) { int u = pq.top().number; pq.pop(); for (int i = 0; i < graph[u].size(); i++) { int v = graph[u][i].to; int d = graph[u][i].length; int w = graph[u][i].weight; if ((dis[v] > dis[u] + d) || (dis[v] == dis[u] + d && cost[v] > cost[u] + w)) { dis[v] = dis[u] + d; cost[v] = cost[u] + w; pq.push(Point(v, dis[v])); } } } return; } int main() { int n, m, d, p; int s, t; while (cin >> n >> m) { if (n == 0 && m == 0) break; memset(graph, 0, sizeof(graph)); //这里编号为从1~n,故fill(dis,dis+n+1,INT_MAX); fill(dis, dis + n + 1, INT_MAX); fill(cost, cost + n + 1, INT_MAX); for (int i = 0; i < m; i++) { int from, to, len, weight; cin >> from >> to >> len >> weight; graph[from].push_back(Edge(to, len, weight)); graph[to].push_back(Edge(from, len, weight)); } cin >> s >> t; Dijkstra(s); cout << dis[t] << " " << cost[t] << endl; } return 0; }