旅游规划
旅游规划
有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
输入格式:
输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2 ≤ N ≤ 500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。
输出格式:
在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。
输入样例:
4 5 0 3 0 1 1 20 1 3 2 30 0 3 4 10 0 2 2 20 2 3 1 20
输出样例:
3 40
解题思路
这道题其实就是在Dijkstra算法的基础上进行改进。在求最短路径的基础上,再加上一个求最少费用,当然最小路径的优先级比最小费用要高,所有只有在两条路径长度相同时,才判断这两条路径哪一条所需费用最小,然后选择费用最小的那一条路径。
下面给出用邻接表的存图方式,以及最原始的Dijkstra算法的AC代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 5 const int INF = 0x3f3f3f3f; 6 7 struct AdjVNode { 8 int adjVer; 9 int len, cost; 10 AdjVNode *next; 11 }; 12 13 struct LGraph { 14 AdjVNode **G; 15 int verN, edgeN; 16 }; 17 18 LGraph *createLGraph(int n, int m); 19 void Dijkstra(LGraph *graph, int src, int dest); 20 21 int main() { 22 int n, m, src, dest; 23 scanf("%d %d %d %d", &n, &m, &src, &dest); 24 LGraph *graph = createLGraph(n, m); 25 Dijkstra(graph, src, dest); 26 27 return 0; 28 } 29 30 LGraph *createLGraph(int n, int m) { 31 LGraph *graph = new LGraph; 32 graph->verN = n; 33 graph->edgeN = m; 34 graph->G = new AdjVNode*[graph->verN]; 35 for (int i = 0; i < graph->verN; i++) { 36 graph->G[i] = NULL; 37 } 38 39 for (int i = 0; i < graph->edgeN; i++) { 40 int v, w, len, cost; 41 scanf("%d %d %d %d", &v, &w, &len, &cost); 42 AdjVNode *tmp = new AdjVNode; 43 tmp->adjVer = w; 44 tmp->len = len; 45 tmp->cost = cost; 46 tmp->next = graph->G[v]; 47 graph->G[v] = tmp; 48 49 tmp = new AdjVNode; 50 tmp->adjVer = v; 51 tmp->len = len; 52 tmp->cost = cost; 53 tmp->next = graph->G[w]; 54 graph->G[w] = tmp; 55 } 56 57 return graph; 58 } 59 60 void Dijkstra(LGraph *graph, int src, int dest) { 61 int dist[graph->verN], cost[graph->verN]; 62 std::fill(dist, dist + graph->verN, INF); 63 std::fill(cost, cost + graph->verN, 0); 64 bool vis[graph->verN] = {false}; 65 66 vis[src] = true; 67 dist[src] = 0; 68 for (AdjVNode *w = graph->G[src]; w; w = w->next) { 69 dist[w->adjVer] = w->len; 70 cost[w->adjVer] = w->cost; 71 } 72 73 while (true) { 74 int minV, min = INF; 75 for (int v = 0; v < graph->verN; v++) { 76 if (!vis[v] && dist[v] < min) { 77 min = dist[v]; 78 minV = v; 79 } 80 } 81 82 vis[minV] = true; 83 if (vis[dest]) break; 84 for (AdjVNode *w = graph->G[minV]; w; w = w->next) { 85 if (dist[w->adjVer] > dist[minV] + w->len) { 86 dist[w->adjVer] = dist[minV] + w->len; 87 cost[w->adjVer] = cost[minV] + w->cost; 88 } 89 else if (dist[w->adjVer] == dist[minV] + w->len) { 90 cost[w->adjVer] = std::min(cost[w->adjVer], cost[minV] + w->cost); 91 } 92 } 93 } 94 95 printf("%d %d\n", dist[dest], cost[dest]); 96 }
再给出我平时用std::vector来存图,同时用std::priority_queue改进后的Dijkstra算法的AC代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <map> 4 #include <queue> 5 #include <vector> 6 #include <algorithm> 7 8 const int INF = 0x3f3f3f3f; 9 10 typedef std::pair<int, int> Pair; 11 12 struct Edge { 13 int to, len, cost; 14 }; 15 16 struct Graph { 17 std::vector<std::vector<Edge> > G; 18 int verN, edgeN; 19 }; 20 21 void Dijkstra(Graph *graph, int src, int dest); 22 23 int main() { 24 int n, m, src, dest; 25 scanf("%d %d %d %d", &n, &m, &src, &dest); 26 Graph *graph = new Graph; 27 graph->verN = n; 28 graph->edgeN = m; 29 graph->G.resize(graph->verN); 30 for (int i = 0; i < graph->edgeN; i++) { 31 int v, w, len, cost; 32 scanf("%d %d %d %d", &v, &w, &len, &cost); 33 graph->G[v].push_back({w, len, cost}); 34 graph->G[w].push_back({v, len, cost}); 35 } 36 37 Dijkstra(graph, src, dest); 38 39 return 0; 40 } 41 42 void Dijkstra(Graph *graph, int src, int dest) { 43 int dist[graph->verN], cost[graph->verN]; 44 std::fill(dist, dist + graph->verN, INF); 45 std::fill(cost, cost + graph->verN, INF); 46 bool vis[graph->verN] = {false}; 47 std::priority_queue<Pair, std::vector<Pair>, std::greater<Pair> > pq; 48 dist[src] = cost[src] = 0; 49 pq.push(Pair(0, src)); 50 51 while (!pq.empty()) { 52 int v = pq.top().second; 53 pq.pop(); 54 if (vis[v]) continue; 55 vis[v] = true; 56 if (vis[dest]) break; 57 58 for (std::vector<Edge>::iterator it = graph->G[v].begin(); it != graph->G[v].end(); it++) { 59 if (!vis[it->to] && dist[v] + it->len < dist[it->to]) { 60 dist[it->to] = dist[v] + it->len; 61 cost[it->to] = cost[v] + it->cost; 62 pq.push(Pair(dist[it->to], it->to)); 63 } 64 else if (!vis[it->to] && dist[v] + it->len == dist[it->to]) { 65 cost[it->to] = std::min(cost[v] + it->cost, cost[it->to]); 66 } 67 } 68 } 69 70 printf("%d %d", dist[dest], cost[dest]); 71 }
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/14819725.html