题目1008:最短路径问题
时间限制:1 秒
内存限制:32 兆
特殊判题:否
提交:3302
解决:988
-
题目描述:
-
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
-
输入:
-
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)
-
输出:
-
输出 一行有两个数, 最短距离及其花费。
-
样例输入:
-
3 2 1 2 5 6 2 3 4 5 1 3 0 0
-
样例输出:
-
9 11
-
来源:
- 2010年浙江大学计算机及软件工程研究生机试真题
- 思路:这题目和普通的最短距离,不一样的地方就是费用,如果到两条到达终点的路径,距离不同,则求最短路同时更新费用,如果有多条到终点距离相同,则应考虑怎么更新费用,整体难度不大.
-
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 1010; const int maxm = 100010; const int INF = 0x7fffffff; int gn, gm; struct info { int d; int p; }; info g[maxn][maxn]; bool vis[maxn]; int dis[maxn]; int price[maxn]; void dijkstra(const int s, const int t) { int i, j; for(i = 1; i <= gn; i++) { dis[i] = INF; price[i] = INF; } dis[s] = 0; price[s] = 0; memset(vis, false, sizeof(vis)); for(i = 1; i <= gn; i++) { int mark = -1, mindis = INF; for(j = 1; j <= gn; j++) { if(!vis[j] && dis[j] < mindis) { mindis = dis[j]; mark = j; } } vis[mark] = true; for(j = 1; j <= gn; j++) { if(!vis[j] && dis[mark] <= dis[j] - g[mark][j].d && g[mark][j].d != INF) {//不存在的边,不会跟新. if(dis[mark] + g[mark][j].d < dis[j]) {//防止无穷大的数据相加时产生溢出. dis[j] = dis[mark] + g[mark][j].d; price[j] = price[mark] + g[mark][j].p; } else { price[j] = min(price[j], price[mark]+g[mark][j].p); } } } } printf("%d %d\n", dis[t], price[t]); } void init() {//初始化.不存在的边为无穷大. int i, j; for(i = 1; i <= gn; i++) { for(j = 1; j <= gn; j++) { if(i == j) continue; else { g[i][j].d = INF; g[i][j].p = INF; } } } } int main() { int x, y, d, p; int i, s, t; while(scanf("%d%d", &gn, &gm) != EOF) { if(gn == 0 && gm == 0) break; init(); for(i = 0; i < gm; i++) { scanf("%d%d%d%d", &x, &y, &d, &p); g[x][y].d = d; g[x][y].p = p; g[y][x].d = d; g[y][x].p = p; } scanf("%d%d", &s, &t); dijkstra(s, t); } return 0; } //第一个程序没有考虑重边的情况所有在HDU3790上WA。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 1110; const int INF = 0x7fffffff; int gn, gm; struct info { int d; int p; }; info g[maxn][maxn]; bool vis[maxn]; int dis[maxn]; int price[maxn]; void dijkstra(const int s, const int t) { int i, j; for(i = 1; i <= gn; i++) { dis[i] = INF; price[i] = INF; } dis[s] = 0; price[s] = 0; memset(vis, false, sizeof(vis)); for(i = 1; i <= gn; i++) { int mark = -1, mindis = INF; for(j = 1; j <= gn; j++) { if(!vis[j] && dis[j] < mindis) { mindis = dis[j]; mark = j; } } vis[mark] = true; for(j = 1; j <= gn; j++) { if(!vis[j] && g[mark][j].d != INF && dis[mark] != INF && dis[mark] <= dis[j] - g[mark][j].d ) {//不存在的边,不会跟新. if(dis[mark] < dis[j] - g[mark][j].d) {//防止无穷大的数据相加时产生溢出. dis[j] = dis[mark] + g[mark][j].d; price[j] = price[mark] + g[mark][j].p; } else { price[j] = min(price[j], price[mark]+g[mark][j].p); } } } } printf("%d %d\n", dis[t], price[t]); } void init() {//初始化.不存在的边为无穷大. int i, j; for(i = 1; i <= gn; i++) { for(j = 1; j <= gn; j++) {//因为i==j时候,自己不会更新自己。 g[i][j].d = INF; g[i][j].p = INF; } } } int main() { int x, y, d, p; int i, s, t; while(scanf("%d%d", &gn, &gm) != EOF) { if(gn == 0 && gm == 0) break; init(); for(i = 0; i < gm; i++) { scanf("%d%d%d%d", &x, &y, &d, &p); if(g[x][y].d == INF){ g[x][y].d = d; g[x][y].p = p; g[y][x].d = d; g[y][x].p = p; } else { if(g[x][y].d > d) { g[x][y].d = d; g[y][x].d = d; g[x][y].p = p; g[y][x].p = p; } if(g[x][y].d == d) { g[x][y].p = min(g[x][y].p, p); g[y][x].p = min(g[y][x].p, p); } } } scanf("%d%d", &s, &t); dijkstra(s, t); } return 0; } /** 7 9 1 2 2 2 1 3 4 5 1 4 3 1 1 5 5 2 2 7 9 7 3 7 5 6 4 7 7 2 5 6 2 2 6 7 2 2 1 7 9 6 **/