旅游规划

旅游规划

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

输入格式:

输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2 ≤ N ≤ 500)是城市的个数,顺便假设城市的编号为0~(N1);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 }

posted @ 2021-05-27 22:52  onlyblues  阅读(186)  评论(0编辑  收藏  举报
Web Analytics