九度OJ刷题——1008:最短路径问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了九度OJ刷题——1008:最短路径问题相关的知识,希望对你有一定的参考价值。
- 题目描述:
-
给你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
这题要注意两点,第一个是可能会存在重边,当两点之间存在重边的时候,存储长度最短的那条,如果有多条最短边,则取费用最低的那条边;第二个是最大值MAX的设置,一开始我设置的是INT_MAX,结果一直WA,因为INT_MAX与其他正值相加后会溢出成为负值,使得判定条件出错,这个一定要多加小心。
源代码:#include <iostream> #include <cstring> using namespace std; const int N = 1001; const int MAX = 1 << 30; int dm[N][N]; int pm[N][N]; int minDis, minCost; void dijkstra(int s, int t, int n); int main(){ int n, m; while(cin >> n >> m){ if(n==0 && m==0) break; //初始化距离矩阵和费用矩阵 for(int i=1; i<=n; i++){ for(int j=1; j<=n; j++){ dm[i][j] = MAX; pm[i][j] = MAX; } } for(int i=0; i<m; i++){ int a, b, d, p; cin >> a >> b >> d >> p; //这两个判断条件是为了处理重边 if(dm[a][b] > d){ dm[a][b] = dm[b][a] = d; pm[a][b] = pm[b][a] = p; } else if(dm[a][b]==d && pm[a][b]>p){ pm[a][b] = pm[b][a] = p; } } int s, t; cin >> s >> t; dijkstra(s, t, n); cout << minDis << ‘ ‘ << minCost << endl; } //system("pause"); return 0; } void dijkstra(int s, int t, int n){ //存储点s到各点的距离和费用 int dis[N]; int cost[N]; for(int i=1; i<=n; i++){ dis[i] = MAX; cost[i] = MAX; } //用于判断是否已经求出s点到某点的最短距离和费用 bool visit[N]; memset(visit, false, sizeof(visit)); //点s到自己的距离和费用为0 dis[s] = 0; cost[s] = 0; for(int i=0; i<n; i++){ int min = MAX; int k; for(int j=1; j<=n; j++){ if(!visit[j] && dis[j]<min){ min = dis[j]; k = j; } } visit[k] = true; for(int j=1; j<=n; j++){ if(!visit[j] && dis[j]>min+dm[k][j]){ dis[j] = min + dm[k][j]; cost[j] = cost[k] + pm[k][j]; } else if(!visit[j] && dis[j]==min+dm[k][j] && cost[j]>cost[k]+pm[k][j]){ cost[j] = cost[k] + pm[k][j]; } } } minDis = dis[t]; minCost = cost[t]; }
以上是关于九度OJ刷题——1008:最短路径问题的主要内容,如果未能解决你的问题,请参考以下文章
九度 1447 最短路径 (Floyd算法和 Dijstra算法)