07-图6 旅游规划(25 分)
有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
输入格式:
输入说明:输入数据的第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 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 5 #define ERROR -1 6 #define false 0 7 #define true 1 8 #define MaxVertexNum 100 9 #define INFINITY 65535 10 typedef int Vertex; 11 typedef int WeightType; 12 typedef char DataType; 13 typedef int bool; 14 15 16 typedef struct ENode *PtrToENode; 17 struct ENode { 18 Vertex V1, V2; 19 WeightType Weight; 20 WeightType Cost; 21 }; 22 typedef PtrToENode Edge; 23 24 typedef struct GNode *PtrToGNode; 25 struct GNode { 26 int Nv; 27 int Ne; 28 WeightType G[MaxVertexNum][MaxVertexNum]; 29 WeightType C[MaxVertexNum][MaxVertexNum]; 30 }; 31 typedef PtrToGNode MGraph; 32 33 MGraph CreateGraph(int VertexNum); 34 void InsertEdge(MGraph Graph, Edge E); 35 MGraph BuildGraph(int Nv, int Ne); 36 void PrintGraph(MGraph Graph); 37 Vertex FindMinDist(MGraph Graph, int dist[], int collected[]); 38 bool Dijkstra(MGraph Graph, int dist[], int path[], int cost[], Vertex S); 39 void PrintDist(MGraph Graph, int dist[]); 40 void PrintPath(int path[], int N); 41 42 MGraph CreateGraph(int VertexNum) 43 { 44 Vertex V, W; 45 MGraph Graph; 46 47 Graph = (MGraph)malloc(sizeof(struct GNode)); 48 Graph->Nv = VertexNum; 49 Graph->Ne = 0; 50 51 for(V=0;V<Graph->Nv;V++) 52 for(W=0;W<Graph->Nv;W++) { 53 Graph->G[V][W] = INFINITY; 54 Graph->C[V][W] = INFINITY; 55 } 56 57 return Graph; 58 } 59 60 void InsertEdge(MGraph Graph, Edge E) 61 { 62 Graph->G[E->V1][E->V2] = E->Weight; 63 Graph->G[E->V2][E->V1] = E->Weight; 64 Graph->C[E->V1][E->V2] = E->Cost; 65 Graph->C[E->V2][E->V1] = E->Cost; 66 } 67 68 MGraph BuildGraph(int Nv, int Ne) 69 { 70 MGraph Graph; 71 Edge E; 72 int i; 73 74 // scanf("%d", &Nv); 75 Graph = CreateGraph(Nv); 76 77 Graph->Ne = Ne; 78 // scanf("%d", &(Graph->Ne)); 79 if(Graph->Ne != 0) { 80 E = (Edge)malloc(sizeof(struct ENode)); 81 for(i=0;i<Graph->Ne;i++) { 82 scanf("%d %d %d %d\n", &E->V1, &E->V2, &E->Weight, &E->Cost); 83 InsertEdge(Graph, E); 84 } 85 } 86 87 return Graph; 88 } 89 90 void PrintGraph(MGraph Graph) 91 { 92 Vertex V, W; 93 printf("Graph:\n"); 94 for(V=0;V<Graph->Nv;V++) { 95 for(W=0;W<Graph->Nv;W++) 96 printf("[%5d %5d]\t" , Graph->G[V][W], Graph->C[V][W]); 97 printf("\n"); 98 } 99 printf("-----------------------\n"); 100 } 101 102 Vertex FindMinDist(MGraph Graph, int dist[], int collected[]) 103 { 104 Vertex MinV, V; 105 int MinDist = INFINITY; 106 107 for(V=0;V<Graph->Nv;V++) { 108 if(collected[V] == false && dist[V]<MinDist) { //未被访问并且距离最小 109 MinDist = dist[V]; 110 MinV = V; 111 } 112 } 113 if(MinDist < INFINITY) 114 return MinV; 115 else return ERROR; 116 } 117 118 bool Dijkstra(MGraph Graph, int dist[], int path[], int cost[], Vertex S) 119 { 120 int collected[MaxVertexNum]; 121 Vertex V, W; 122 123 /* 初始化:此处默认邻接矩阵中不存在的边用INFINITY表示 */ 124 for(V=0;V<Graph->Nv;V++) { 125 dist[V] = Graph->G[S][V]; 126 cost[V] = Graph->C[S][V]; 127 if(dist[V]<INFINITY) 128 path[V] = S; 129 else 130 path[V] = -1; 131 collected[V] = false; 132 } 133 // PrintPath(path, Graph->Nv); 134 /* 先将起点收入集合 */ 135 dist[S] = 0; 136 collected[S] = true; 137 138 while(1) { 139 /* V = 未被收录顶点中dist最小者 */ 140 V = FindMinDist(Graph, dist, collected); 141 // printf("[FindMinDist] V:%d\n", V); 142 if(V == ERROR) /* 若这样的V不存在 */ 143 break; /* 算法结束 */ 144 collected[V] = true; /* 收录 */ 145 for(W=0;W<Graph->Nv;W++) { /* 对图中的每个顶点W */ 146 /* 若W是V的邻接点并且未被收录 */ 147 if(collected[W]==false && Graph->G[V][W]<INFINITY) { 148 if(Graph->G[V][W]<0) /* 若有负边 */ 149 return false; /* 不能正确解决,返回错误标记 */ 150 /* 若收录V使得dist[W]变小(两点距离比一点距离短) */ 151 if(dist[V]+Graph->G[V][W]<dist[W]) { 152 dist[W] = dist[V] + Graph->G[V][W]; /* 更新dist[W] */ 153 // printf("[FindMinDist] dist[W(%d)]=%d\n", W, dist[W]); 154 path[W] = V; /* 更新S到W的路径 */ 155 cost[W] = cost[V] + Graph->C[V][W]; 156 } else if((dist[V]+Graph->G[V][W] == dist[W]) 157 && (cost[V] + Graph->C[V][W] < cost[W])) { 158 cost[W] = cost[V] + Graph->C[V][W]; 159 } 160 } 161 } 162 } 163 164 return true; /* 算法执行完毕,返回正确标记 */ 165 } 166 167 void PrintDist(MGraph Graph, int dist[]) 168 { 169 Vertex V; 170 for(V=0;V<Graph->Nv;V++) { 171 printf("%d ", dist[V]); 172 } 173 printf("\n"); 174 } 175 176 void PrintPath(int path[], int N) 177 { 178 int i; 179 printf("[Path] "); 180 for(i=0;i<N;i++) 181 printf("%d ",path[i]); 182 printf("\n"); 183 } 184 185 int main() 186 { 187 int N, M; 188 Vertex S, D; 189 int *dist, *path, *cost; 190 MGraph Graph; 191 scanf("%d %d %d %d\n", &N, &M, &S, &D); 192 dist = (int *)malloc(sizeof(int)*N); 193 path = (int *)malloc(sizeof(int)*N); 194 cost = (int *)malloc(sizeof(int)*N); 195 Graph = BuildGraph(N, M); 196 // PrintGraph(Graph); 197 Dijkstra(Graph, dist, path, cost, S); 198 // PrintPath(path, N); 199 printf("%d %d\n", dist[D], cost[D]); 200 return 0; 201 }
无欲速,无见小利。欲速,则不达;见小利,则大事不成。