//常规dijkstra算法,先考虑最短路径排列,再建数组更新费用,更新费用时注意要在最短路径的前提下更新; //关于数组规模的问题,目的地可能为n,目的地又可能作为容器指标,所以容器数量至少为n+1; #include <cstdint> #include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<vector> using namespace std; const int MAXN = 1000; const int INF = INT16_MAX; struct Edge { int to; int length; int price; Edge(int b, int d, int p): to(b), length(d), price(p) {} }; struct Point { int number; int distance; int fee; Point(int num, int dis, int fee): number(num), distance(dis), fee(fee) {} bool operator<(const Point& p)const { if (distance != p.distance) { return distance > p.distance; } else { return fee > p.fee; } } }; vector<Edge>G[MAXN]; int dis[MAXN]; int Fee[MAXN]; void dijkstra(int s) { priority_queue<Point>Q; dis[s] = 0; Fee[s] = 0; Q.push(Point(s, dis[s], Fee[s])); while (!Q.empty()) { int u = Q.top().number; Q.pop(); for (int i = 0; i < G[u].size(); i++) { int d = G[u][i].length;//距离 int v = G[u][i].to; //目的地 int p = G[u][i].price; //价格 if (dis[v] > dis[u] + d) { dis[v] = dis[u] + d; Fee[v] = Fee[u] + p; Q.push(Point(v, dis[v], Fee[v])); } else if (dis[v] == dis[u] + d) { if (Fee[v] > Fee[u] + p) { Fee[v] = Fee[u] + p; Q.push(Point(v, dis[v], Fee[v])); } } } } return ; } int main() { int n, m; while (scanf("%d %d", &n, &m) != EOF) { if (n == 0 && m == 0) { break; } fill(dis, dis + n + 1, INF); //n+1 fill(Fee, Fee + n + 1, INF); ///n+1 memset(G, 0, sizeof(G)); for (int i = 0; i < m; i++) { int a; int b; int d; int p; scanf("%d %d %d %d", &a, &b, &d, &p); G[a].push_back(Edge(b, d, p)); G[b].push_back(Edge(a, d, p)); } int u, v; scanf("%d %d", &u, &v); dijkstra(u); printf("%d %d\n", dis[v], Fee[v]); } return 0; }