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 N integers, 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, c2and 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来全局搜索,也可以利用分支限界的思想来提高效率,只需要一个判读语句即可。
注意:
- DFS可能需要传比较多的参数,可以将这些参数定义为全局变量即可
- 可以利用分支限界法的思想,对于不满足最小的路径不再往下搜索,提升效率
代码:(C++)
#include<iostream>
#include<cmath>
#include<cstring>
#define MAX_VALUE 501
#define MAX_INT 0x3f3f3f3f
using namespace std;
int n, m, cur, obj;
int map[MAX_VALUE][MAX_VALUE]; //保存地图,线路
int rescue[MAX_VALUE]; //保存各城市救援人数
int min_dis = MAX_INT; //保存最小距离
int max_res = 0; //保存最大助手
int visited[MAX_VALUE]; //保存是否访问过该城市
int cur_way = 0; //当前路线距离
int cur_res = 0; //当前最大助手
int num = 0; //记录有多少最短路径
void DFS(int c)
{
if(c == obj)
{
if(cur_way < min_dis)
{
num = 1; //找到更短了的,重置为1
max_res = cur_res;
min_dis = cur_way;
}
else if(cur_way == min_dis)
{
num++; //找到一条一样长的路径,条数+1
max_res = max(max_res, cur_res);
}
}
else
{
visited[c] = 1; //说明此城市被访问了
for(int i=0; i<n; i++)
{
if(map[c][i] != -1 && visited[i] != 1)
{
cur_res += rescue[i];
cur_way += map[c][i];
if(cur_way <= min_dis) //分支限界一下,提高效率
DFS(i); //深度遍历
cur_res -= rescue[i]; //回溯
cur_way -= map[c][i];
}
}
visited[c] = 0; //该城市的所有路径访问完了,回溯之后,设置为可以访问了
}
}
int main()
{
cin>>n>>m>>cur>>obj;
memset(map,-1,sizeof(map));
memset(visited, 0, sizeof(visited));
for(int i=0; i<n; i++)
cin>>rescue[i];
for(int i=0; i<m; i++)
{
int x,y,dis;
cin>>x>>y>>dis;
map[x][y] = dis;
map[y][x] = dis; //无向图
}
cur_res += rescue[cur]; //带上自己城市的帮手
DFS(cur);
cout<<num<<" "<<max_res;
return 0;
}
效率分析:
-
未使用分支限界思想
-
使用分支限界思想