甲级1003 Emergency
As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.
Input Specification:
Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C1 and C2 - the cities that you are currently in and that you must save, respectively. The next line contains Nintegers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1, c2 and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1 to C2.
Output Specification:
For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.
Sample Input:
5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
Sample Output:
2 4
题意:有几座城市,每座城市中有救援的人手,然后救援大队长从一座城市出发,到另一座城市,找到最短的路共有几条,可带的最多的救援人手有多少(每经过一个城市,就可以把这个城市的人手带走,相当于累加)
分析:递归DFS,当遇到终点时即返回。注意最后输出的是最短的路有几条和可携带的最多救援人手。(WA就是因为输出成最短路径长度了)
在写的过程中还有一个地方也当时没能一次写对:在求最多救援人手的时候,条件应该是
-
如果当前已经过的距离和已知的最短距离相等时,则如果当前人手大于已知的最多救援人手,就刷新最多救援人手。
- 若当前经过的距离比已知的最短距离更短时,直接刷新最短距离和最大救援人手。代码如下:
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 5 int N, M; //城市数,道路数 6 int outset, des; 7 int minLen=-1, maxRes=-1, roadCount; //最短距离,最大救援数量,道路计数 8 int currentLen, currentWeight; //当前累计长度,当前累计权重 9 int cmap[505][505]; 10 int city_rescue[505]; 11 bool vis[505]; //判断该城市是否被访问过 12 13 void init() 14 { 15 for (int i = 0; i < 505; i++) 16 for (int j = 0; j < 505; j++) 17 cmap[i][j] = -1; //初始化各城市之间没有道路 18 } 19 void DFS(int begin) 20 { 21 currentWeight += city_rescue[begin]; //加上该起点城市的权重 22 if (begin == des) //如果已经访问至终点 23 { 24 if (minLen == -1 || currentLen < minLen) 25 { 26 minLen = currentLen; 27 maxRes = currentWeight; 28 roadCount = 1; 29 } 30 else if (currentLen == minLen) 31 { 32 roadCount++; 33 if(currentWeight>maxRes) 34 maxRes = currentWeight; 35 } 36 37 currentWeight -= city_rescue[begin]; 38 return; 39 } 40 41 vis[begin] = true; 42 for (int i = 0; i < N; i++) 43 { 44 if (cmap[begin][i] != -1 && vis[i] == false) //与起点城市有路且未被访问 45 { 46 currentLen += cmap[begin][i]; //访问该城市前,路径长度先加上 47 DFS(i); //递归访问i城市 48 currentLen -= cmap[begin][i]; 49 } 50 } 51 currentWeight -= city_rescue[begin]; 52 vis[begin] = false; 53 } 54 int main() 55 { 56 init(); 57 scanf("%d %d %d %d", &N, &M, &outset, &des); 58 for (int i = 0; i < N; i++) 59 scanf("%d", &city_rescue[i]); 60 for (int i = 0; i < M; i++) 61 { 62 int a, b, weight; 63 scanf("%d %d %d", &a, &b, &weight); 64 cmap[a][b] = cmap[b][a] = weight; 65 } 66 DFS(outset); 67 printf("%d %d", roadCount, maxRes); 68 return 0; 69 }
贴一下DFS伪代码
1 DFS(u) { 2 vis[u] = true; 3 for (从u出发能达到的所有顶点v) 4 if vis[v] == false 5 DFS(v); //递归访问 6 }