给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
Input输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)Output输出 一行有两个数, 最短距离及其花费。Sample Input
3 2 1 2 5 6 2 3 4 5 1 3 0 0
Sample Output
9 11
#include <cstdio> #include <iostream> #include <cmath> #include <string> #include <cstring> #include <algorithm> using namespace std; #define ll long long const int inf = 0x3f3f3f3f; const int maxn = 1e4+8; int n, m; int dis[maxn][maxn], d[maxn], cost[maxn][maxn], co[maxn]; bool sign[maxn]; void dij(int s) { fill(sign, sign+maxn, 0); fill(d, d+n+1, inf); fill(co, co+n+1, inf); d[s] = co[s] = 0; for(int i = 0; i <= n; i++)//一个一个点的遍历,找出最短路径 { int miao, ying = inf; for(int j = 0; j <= n; j++) if(!sign[j] && d[j] <= ying) ying = d[miao = j];//把最短距离的那个点标记起来,方便后面的计算 sign[miao] = 1; for(int j = 0; j <= n; j++)//在i点的基础上,一个一个点的遍历,找出由起点到重点的最短距离 { if(d[j]>d[miao]+dis[miao][j])//如果(从起点到j点的距离)大于(从起点到miao点的距离)+(从miao点的距离到j点的距离) { d[j] = d[miao]+dis[miao][j]; co[j] = co[miao]+cost[miao][j]; } else if(d[j] == d[miao]+dis[miao][j] && co[j]>co[miao]+cost[miao][j])//如果距离相等,但(从起点到j点的花费)大于(从起点到miao点的花费)+(从miao点的距离到j点的花费) co[j] = co[miao]+cost[miao][j]; } } } int main() { int a, b, di, p; while(~scanf("%d%d", &n, &m) &&(n+m)) { for(int i = 0; i <= n; i++) for(int j = 0; j <= n; j++) { dis[i][j] = inf; cost[i][j] = inf; } for(int i = 0; i<m; i++) { scanf("%d%d%d%d", &a, &b, &di, &p); if(dis[a][b]>di) { dis[a][b] = di; dis[b][a] = di; cost[a][b] = p; cost[b][a] = p; } else if(dis[a][b] == di && cost[a][b]>p) { cost[a][b] = p; cost[b][a] = p; } } int s, e; scanf("%d%d", &s, &e); dij(s); printf("%d %d ", d[e], co[e]); } return 0; }