题目链接
https://pintia.cn/problem-sets/994805342720868352/problems/994805464397627392
题解
题目要求
- 输入
- N:正整数,不超过500,结点的数量,索引为[0,N-1]
- M:正整数,边的数量
- S:起点索引
- D:终点索引
- M条边
- 输出
- 最短路径经过的结点
- 总距离
- 总成本
解题思路
该题在普通最短路径题目基础上补充了2点
我是先做了PAT甲级1018Public Bike Management,这两题很相似,1018更难,这题更简单。
-
输出最短路径经过的结点
因为最终的最短路径只有一条,所以保存最短路径中每个结点的前一个结点,最终从D往回遍历即可
-
优先考虑距离,再考虑成本
通过if语句实现
代码
最后生成path时我是递归存入vector,其实也可以直接迭代生成。
// Problem: PAT Advanced 1030
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805464397627392
// Tags: 最短路 图 dijkstra 单源最短路 BFS
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 500;
const int INF = 9999999;
int n, m, s, d;
bool visited[MAXN];
int minDis[MAXN];
int minCost[MAXN];
int dis[MAXN][MAXN];
int cost[MAXN][MAXN];
int pre[MAXN];
vector<int> path;
void getPath(int v){
path.push_back(v);
if (v != s){
getPath(pre[v]);
}
}
int main()
{
fill(minDis, minDis + MAXN, INF);
fill(minCost, minCost + MAXN, INF);
fill(dis[0], dis[0] + MAXN * MAXN, INF);
fill(cost[0], cost[0] + MAXN * MAXN, INF);
scanf("%d %d %d %d", &n, &m, &s, &d);
int a, b;
for (int i = 0; i < m; i++){
scanf("%d %d", &a, &b);
scanf("%d %d", &dis[a][b], &cost[a][b]);
dis[b][a] = dis[a][b];
cost[b][a] = cost[a][b];
}
minDis[s] = 0;
minCost[s] = 0;
for (int i = 0; i < n; i++){
int u = -1, minD = INF;
for (int j = 0; j < n; j++){
if (!visited[j] && minDis[j] < minD){
minD = minDis[j];
u = j;
}
}
if (u == -1) break;
visited[u] = true;
for (int v = 0; v < n; v++){
if (!visited[v] && dis[u][v] != INF){
if (minDis[u] + dis[u][v] < minDis[v]){
minDis[v] = minDis[u] + dis[u][v];
minCost[v] = minCost[u] + cost[u][v];
pre[v] = u;
}
else if (minDis[u] + dis[u][v] == minDis[v] && minCost[u] + cost[u][v] < minCost[v]){
minCost[v] = minCost[u] + cost[u][v];
pre[v] = u;
}
}
}
}
getPath(d);
for (auto iter = path.rbegin(); iter != path.rend(); iter++)
printf("%d ", *iter);
printf("%d %d", minDis[d], minCost[d]);
return 0;
}
作者:@臭咸鱼
转载请注明出处:https://www.cnblogs.com/chouxianyu/
欢迎讨论和交流!