在邻接矩阵中有两个 一个是长度G 一个是收费cost
在dijkstra基础上,增加了cost的更新,以及路径长度相等时,选取最小cost
有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
输入格式:
输入说明:输入数据的第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
1 /* 图的邻接矩阵表示法 */ 2 #include <iostream> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <queue> 6 using namespace std; 7 8 #define ERROR -1 9 #define MaxVertexNum 505 /* 最大顶点数设为100 */ 10 #define INFINITY 65535 /* 设为双字节无符号正数的最大值65535*/ 11 typedef int Vertex; /* 用顶点下标表示顶点,为整型 */ 12 typedef int WeightType; /* 边的权值设为整型 */ 13 typedef char DataType; /* 顶点存储的数据类型设为字符型 */ 14 15 /* 边的定义 */ 16 typedef struct ENode *PtrToENode; 17 struct ENode{ 18 Vertex V1, V2; /* 有向边<V1, V2> */ 19 WeightType Weight; /* 长度 */ 20 WeightType cost; /* 过路费 */ 21 }; 22 typedef PtrToENode Edge; 23 24 /* 图结点的定义 */ 25 typedef struct GNode *PtrToGNode; 26 struct GNode{ 27 int Nv; /* 顶点数 */ 28 int Ne; /* 边数 */ 29 WeightType G[MaxVertexNum][MaxVertexNum]; /* 邻接矩阵存放路径长度 */ 30 WeightType cost[MaxVertexNum][MaxVertexNum]; /* 邻接矩阵存放过路费 */ 31 /* 注意:很多情况下,顶点无数据,此时Data[]可以不用出现 */ 32 }; 33 typedef PtrToGNode MGraph; /* 以邻接矩阵存储的图类型 */ 34 35 MGraph CreateMGraph( int VertexNum ) 36 { /* 初始化一个有VertexNum个顶点但没有边的图 */ 37 Vertex V, W; 38 MGraph Graph; 39 40 Graph = (MGraph)malloc(sizeof(struct GNode)); /* 建立图 */ 41 Graph->Nv = VertexNum; 42 Graph->Ne = 0; 43 /* 初始化邻接矩阵 */ 44 /* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */ 45 for (V=0; V<Graph->Nv; V++) 46 for (W=0; W<Graph->Nv; W++) { 47 Graph->G[V][W] = INFINITY; 48 Graph->cost[V][W] = INFINITY; 49 } 50 return Graph; 51 } 52 53 void InsertMEdge( MGraph Graph, Edge E ) 54 { 55 /* 插入边 <V1, V2> */ 56 Graph->G[E->V1][E->V2] = E->Weight; 57 Graph->cost[E->V1][E->V2] = E->cost; 58 /* 若是无向图,还要插入边<V2, V1> */ 59 Graph->G[E->V2][E->V1] = E->Weight; 60 Graph->cost[E->V2][E->V1] = E->cost; 61 } 62 63 MGraph BuildMGraph(int Nv,int Ne) 64 { 65 MGraph Graph; 66 Edge E; 67 Vertex V; 68 69 // scanf("%d", &Nv); /* 读入顶点个数 */ 70 Graph = CreateMGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */ 71 72 // scanf("%d", &(Graph->Ne)); /* 读入边数 */ 73 Graph->Ne = Ne; 74 if ( Graph->Ne != 0 ) { /* 如果有边 */ 75 E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */ 76 /* 读入边,格式为"起点 终点 长度 收费额",插入邻接矩阵 */ 77 for (int i=0; i<Graph->Ne; i++) { 78 scanf("%d %d %d %d", &E->V1, &E->V2, &E->Weight, &E->cost); 79 /* 注意:如果权重不是整型,Weight的读入格式要改 */ 80 InsertMEdge( Graph, E ); 81 } 82 } 83 return Graph; 84 } 85 86 /* 邻接矩阵存储 - 有权图的单源最短路算法 */ 87 Vertex FindMinDist( MGraph Graph, int dist[], int collected[] ) 88 { /* 返回未被收录顶点中dist最小者 */ 89 Vertex MinV, V; 90 int MinDist = INFINITY; 91 92 for (V=0; V<Graph->Nv; V++) { 93 if ( collected[V]==false && dist[V] < MinDist) { 94 /* 若V未被收录,且dist[V]更小 */ 95 MinDist = dist[V]; /* 更新最小距离 */ 96 MinV = V; /* 更新对应顶点 */ 97 } 98 } 99 if (MinDist < INFINITY) /* 若找到最小dist */ 100 return MinV; /* 返回对应的顶点下标 */ 101 else return ERROR; /* 若这样的顶点不存在,返回错误标记 */ 102 } 103 104 bool Dijkstra( MGraph Graph, int dist[], int cost[], int path[], Vertex S ) 105 { 106 int collected[MaxVertexNum]; 107 Vertex V, W; 108 109 /* 初始化:此处默认邻接矩阵中不存在的边用INFINITY表示 */ 110 for ( V=0; V < Graph->Nv; V++ ) { 111 dist[V] = Graph->G[S][V]; 112 path[V] = -1; 113 collected[V] = false; 114 cost[V] = Graph->cost[S][V]; 115 } 116 /* 先将起点收入集合 */ 117 dist[S] = 0; 118 cost[S] = 0; 119 collected[S] = true; 120 121 while (1) { 122 /* V = 未被收录顶点中dist最小者 */ 123 V = FindMinDist( Graph, dist, collected ); 124 if ( V==ERROR ) /* 若这样的V不存在 */ 125 break; /* 算法结束 */ 126 collected[V] = true; /* 收录V */ 127 for( W = 0; W < Graph->Nv; W++ ) /* 对图中的每个顶点W */ 128 /* 若W是V的邻接点并且未被收录 */ 129 if ( collected[W]==false && Graph->G[V][W]<INFINITY ) { 130 if ( Graph->G[V][W]<0 ) /* 若有负边 */ 131 return false; /* 不能正确解决,返回错误标记 */ 132 /* 若收录V使得dist[W]变小 */ 133 if ( dist[V]+Graph->G[V][W] < dist[W] ) { 134 dist[W] = dist[V] + Graph->G[V][W]; /* 更新dist[W] */ 135 path[W] = V; /* 更新S到W的路径 */ 136 cost[W] = cost[V] + Graph->cost[V][W]; 137 }else if( (dist[V]+Graph->G[V][W] == dist[W] ) //若路径长度相等 取最小cost的 138 && (cost[W] > cost[V] + Graph->cost[V][W]) ) 139 cost[W] = cost[V] + Graph->cost[V][W]; 140 } 141 } /* while结束*/ 142 return true; /* 算法执行完毕,返回正确标记 */ 143 } 144 145 int main() 146 { 147 //顶点数N城市数 边数M公路数 出发地S 目的城市D 148 int N, M, S, D; 149 cin >> N >> M >> S >> D; 150 MGraph graph; 151 graph = BuildMGraph(N,M); 152 153 WeightType dist[MaxVertexNum] = {INFINITY}; 154 WeightType cost[MaxVertexNum] = {INFINITY}; 155 WeightType path[MaxVertexNum] = {0}; 156 int collected[MaxVertexNum] = {false}; 157 158 Dijkstra( graph, dist, cost, path, S); 159 cout << dist[D] << " " << cost[D] << endl; 160 161 return 0; 162 }