PTA数据结构与算法题目集(中文) 7-35 城市间紧急救援 (25 分)
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出4个正整数N、M、S、D,其中N(2)是城市的个数,顺便假设城市的编号为0 ~ (;M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。
第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。
输出格式:
第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。
输入样例:
4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2
输出样例:
2 60 0 1 3
题目分析:一道图的单源有权最短路径题 利用Dijkstra算法 该题中有2个决定性因素 所以优先判断的那个 要更新次重要的那个因素
再者,计算最短路径的条数 要注意计算的方法 是利用前一个节点与后一个节点之间的关系来计算 具体来说 对于每一个找到最小路径的节点,它最短路径的次数与它前一个节点的最短路径次数相同,如果找到了另一种最短路径,那么总的最短路径次数要加上其另一种最短路径的上一个节点最短路径的次数
最后,在输出路径时 要利用到栈,仔细想想,递归也是用类似于栈的思想来实现的,所以可以用递归来实现输出
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<stdio.h> 3 #include<string.h> 4 #include<malloc.h> 5 #define INIFITY 65535 6 typedef struct ENode* Edge; 7 struct ENode 8 { 9 int V1,V2; 10 int Weight; 11 }; 12 typedef struct GNode* Graph; 13 struct GNode 14 { 15 int G[510][510]; 16 int Nv; 17 int Ne; 18 }; 19 20 int IsEdge(Graph Gra, int V1, int V2) 21 { 22 return Gra->G[V1][V2]!=INIFITY; 23 } 24 25 void Insert(Graph Gra, Edge E) 26 { 27 Gra->G[E->V1][E->V2] = E->Weight; 28 Gra->G[E->V2][E->V1] = E->Weight; 29 } 30 31 Graph CreateGraph(int Nv) 32 { 33 Graph Gra = (Graph)malloc(sizeof(struct GNode)); 34 Gra->Nv = Nv; 35 Gra->Ne = 0; 36 for (int i = 0; i < Gra->Nv; i++) 37 for (int j = 0; j < Gra->Nv; j++) 38 Gra->G[i][j] = INIFITY; 39 return Gra; 40 } 41 42 int WeightInNode[510]; 43 int SumOfWeight[510]; 44 45 int Dist[510]; 46 int Path[510]; 47 int Times[510]; 48 int Collected[510]; 49 int FindMinDist(Graph Gra) 50 { 51 int MinDist = INIFITY; 52 int Min = -1; 53 for (int i = 0; i < Gra->Nv; i++) 54 { 55 if (!Collected[i]&&Dist[i] < MinDist) 56 { 57 MinDist = Dist[i]; 58 Min = i; 59 } 60 } 61 if (MinDist != INIFITY) 62 return Min; 63 else 64 return 0; 65 } 66 67 void Dijkstra(Graph Gra, int V) 68 { 69 SumOfWeight[V] = WeightInNode[V]; 70 for (int i = 0; i < Gra->Nv; i++) 71 { 72 Dist[i] = Gra->G[V][i]; 73 if (IsEdge(Gra, V, i)) 74 { 75 SumOfWeight[i] = SumOfWeight[V] + WeightInNode[i]; 76 Path[i] = V; 77 Times[i] = 1; 78 } 79 else 80 Path[i] = -1; 81 } 82 83 Dist[V] = 0; 84 Collected[V] = 1; 85 while (1) 86 { 87 int i = FindMinDist(Gra); 88 if (!i) 89 break; 90 Collected[i] = 1; 91 for (int j = 0; j < Gra->Nv; j++) 92 { 93 if(!Collected[j]&&IsEdge(Gra,i,j)) 94 if (Dist[i] + Gra->G[i][j] < Dist[j]) 95 { 96 Times[j] = Times[i]; 97 Dist[j] = Dist[i] + Gra->G[i][j]; 98 SumOfWeight[j] = SumOfWeight[i] + WeightInNode[j]; 99 Path[j] = i; 100 } 101 else if (Dist[i] + Gra->G[i][j] == Dist[j]) 102 { 103 Times[j] += Times[i]; 104 if (SumOfWeight[i] + WeightInNode[j] >=SumOfWeight[j]) 105 { 106 SumOfWeight[j] = SumOfWeight[i] + WeightInNode[j]; 107 Path[j] = i; 108 } 109 } 110 } 111 } 112 } 113 114 int k = 0; 115 void Print(int D) 116 { 117 if (Path[D] != -1) 118 { 119 Print(Path[D]); 120 } 121 if (k == 0) 122 { 123 printf("%d", D); 124 k++; 125 } 126 else 127 printf(" %d",D); 128 } 129 130 int main() 131 { 132 int N, M, S, D; 133 scanf("%d%d%d%d", &N, &M, &S, &D); 134 Graph Gra = CreateGraph(N); 135 Gra->Ne = M; 136 for (int i = 0; i < Gra->Nv; i++) 137 scanf("%d", &WeightInNode[i]); 138 Edge E = (Edge)malloc(sizeof(struct ENode)); 139 for (int i = 0; i < Gra->Ne; i++) 140 { 141 scanf("%d%d%d", &(E->V1), &(E->V2), &(E->Weight)); 142 Insert(Gra, E); 143 } 144 Dijkstra(Gra, S); 145 printf("%d %d ", Times[D], SumOfWeight[D]); 146 Print(D); 147 return 0; 148 }