题目要求:
有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径
输出格式:
输入说明:输入数据的第 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
题解:
思路如注释所示,可通过所有测试点。
#include<bits/stdc++.h>
using namespace std;#define MaxVertexNum 500 //最大顶点数
#define INFINITY 65535
#define ERROR -1
typedef int Vertex; //顶点类型为整形
typedef int WeightType; //权值为整形 typedef struct ENode *PtrToENode; //边结点
struct ENode {Vertex V1, V2; //有向边<V1,V2> WeightType Weight; //权重 WeightType cost; //收费额
};
typedef PtrToENode Edge;typedef struct GNode *PtrToGNode; //存储图
struct GNode {int Nv; //顶点数 int Ne; //边数 WeightType G[MaxVertexNum][MaxVertexNum];WeightType Cost[MaxVertexNum][MaxVertexNum];
};
typedef PtrToGNode MGraph; //邻接矩阵存储图 Vertex start, final;MGraph CreateGraph(int VertexNum) {Vertex V, W;MGraph Graph;Graph = (MGraph)malloc(sizeof(struct GNode));Graph->Nv = VertexNum;Graph->Ne = 0;for (V = 0; V < Graph->Nv; V++)for (W = 0; W < Graph->Nv; W++) {Graph->G[V][W] = INFINITY;Graph->Cost[V][W] = INFINITY;}return Graph;
}void InsertEdge(MGraph Graph, Edge E) {// 因为是无向图插入<V1,V2>,<V2,V1> Graph->G[E->V1][E->V2] = E->Weight;Graph->Cost[E->V1][E->V2] = E->cost;Graph->G[E->V2][E->V1] = E->Weight;Graph->Cost[E->V2][E->V1] = E->cost;
}MGraph BuildGraph() {MGraph Graph;Edge E;int Nv, i;cin >> Nv;Graph = CreateGraph(Nv);cin >> Graph->Ne; // 读入边数 cin >> start >> final; // 读入起点和终点 if (Graph->Ne != 0) {E = (Edge)malloc(sizeof(struct ENode));for (i = 0; i < Graph->Ne; i++) {cin >> E->V1 >> E->V2 >> E->Weight >> E->cost;InsertEdge(Graph, E);}}return Graph;
}Vertex FindMinDist(MGraph Graph, int dist[], int collected[]) {Vertex MinV = ERROR;int MinDist = INFINITY;for (Vertex V = 0; V < Graph->Nv; V++) {if (collected[V] == 0 && dist[V] < MinDist) {MinDist = dist[V];MinV = V;}}return MinV;
}void Dijkstra(MGraph Graph, int cost[], int dist[], Vertex S) {int collected[MaxVertexNum] = { 0 };Vertex V, W;// 初始化dist和cost数组,若不存在边则初始化为INFINITYfor (V = 0; V < Graph->Nv; V++) {dist[V] = Graph->G[S][V];cost[V] = Graph->Cost[S][V];collected[V] = 0;}// 初始化起始结点 dist[S] = 0;cost[S] = 0;collected[S] = 1;while (1) {// V是未被收录顶点中dist最小者V = FindMinDist(Graph, dist, collected);if (V == ERROR) // 所有结点都处理完 break; // 算法结束 collected[V] = 1;for (W = 0; W < Graph->Nv; W++) {if (collected[W] == 0 && Graph->G[V][W] < INFINITY) {if (dist[V] + Graph->G[V][W] < dist[W]) {dist[W] = dist[V] + Graph->G[V][W];cost[W] = cost[V] + Graph->Cost[V][W];} else if (dist[V] + Graph->G[V][W] == dist[W] &&cost[V] + Graph->Cost[V][W] < cost[W]) {cost[W] = cost[V] + Graph->Cost[V][W];}}}}return; // 算法结束
}int main() {MGraph Graph = BuildGraph();int dist[MaxVertexNum], cost[MaxVertexNum]; // dist, cost数组为起点到一个结点的路程和花费 Dijkstra(Graph, cost, dist, start);cout << dist[final] << " " << cost[final]; return 0;
}
总结:
1.用cost和dist数组记录从起始点到一个结点的花费和距离
2.此题主要用到dijkstra算法,找到从一个结点到另一个结点的最短路径,再此基础上加入了价格这个衡量标准,所以在buildgraph时要把每条边之间的价格记录下来,当算法找到同样短的路径时,选择花费较少的那条路径