HDU3790-最短路径问题
题目链接:点击打开链接
Problem Description
给你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
思路:最短路模板题,涉及两个标尺,可以保险的先保存路径,再计算,这个可以直接算。看注释。
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXV = 1010;
const int INF = 0x3f3f3f;
int d[MAXV], G[MAXV][MAXV];//矩阵
int c[MAXV], cost[MAXV][MAXV];//花费
int n, m, st, ed;
void dijsktra(int st) {
bool vis[MAXV] = {false};
fill(d, d + MAXV, INF);//注意这里的初始化
fill(c, c + MAXV, INF);
d[st] = 0;
c[st] = 0;
for(int i = 1; i <= n; i++) {//模板
int u = -1, MIN = INF;
for(int j = 1; j <= n; j++) {
if(vis[j] == false && d[j] < MIN) {
u = j;
MIN = d[j];
}
}
if(u == -1) return;
vis[u] = true;
for(int v = 1; v <= n; v++) {
if(vis[v] == false && G[u][v] != INF) {
if(d[u] + G[u][v] < d[v]) {//短的话,都更新
d[v] = d[u] + G[u][v];
c[v] = c[u] + cost[u][v];
} else if(d[u] + G[u][v] == d[v] && c[u] + cost[u][v] < c[v]) {//相等的话,更新花费
c[v] = c[u] + cost[u][v];
}
}
}
}
}
int main() {
int a, b, w, p;
while(scanf("%d %d", &n, &m) != EOF, n || m) {
fill(G[0], G[0] + MAXV * MAXV, INF);
fill(cost[0], cost[0] + MAXV * MAXV, INF);
while(m--) {
scanf("%d %d %d %d", &a, &b, &w, &p);
if(G[a][b] > w) {//最大的坑点。可能有多条路径。!!!!!
G[a][b] = G[b][a] = w;
cost[a][b] = cost[b][a] = p;
} else if(G[a][b] == w && cost[a][b] > p) {
cost[a][b] = cost[b][a] = p;
}
}
scanf("%d %d", &st, &ed);
dijsktra(st);
printf("%d %d\n", d[ed], c[ed]);
}
return 0;
}
埋骨何须桑梓地,人生无处不青山