1003. Emergency (25)
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
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, 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
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.
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 1Sample Output
2 4
题意:
某地发生了灾难,给出每个地区救援队的数量以及地区间的无向边,求起始地到目的地的最短距离和救援队总数。若有多个最短路,输出路径上救援队最多的。
考点:
1. 带附加权值的最短路
题解:
1.可用两遍DFS,第一遍求最短路,第二遍求最多救援队。
2.可用一遍DFS同时求最短路和最多救援队,更新条件为:
当距离更短时更新最短距离+救援队总数
当距离相等且救援队更多时更新救援队总数
3.可用SFPA,但要将普通队列改为优先队列。优先条件为离源点更近的在前,更新条件与解法2相同。优先队列是为了避免B点用了从A点目前最短路上的救援队总数后,A点的最短路被更新,救援队总数也被更新。此时B点将得到了错误的救援队总数。
坑点:
无
解法2:
#include <iostream>
#include <queue>
using namespace std;
int min_d, ans, max_;
int n, m, c1, c2;
int rt[501];
bool v[501];
int e[501][501];
void dfs(int t, int d, int num)
{
int i;
if (d > min_d) return;
num += rt[t];
if(t == c2){
if (d < min_d){
min_d = d;
ans = 1;
max_ = num;
}
else if (d == min_d){
ans++;
if(num > max_) max_ = num;
}
return;
}
for(i = 0; i < n; i++)
{
if (!v[i] && e[t][i] != -1 && t != i){
v[i] = true;
dfs(i, d + e[t][i], num);
v[i] = false;
}
}
}
int main()
{
cin >> n >> m >> c1 >> c2;
int i, j;
int a, b, c;
for(i = 0; i < n; i++) cin >> rt[i];
for(i = 0; i < n; i++)
for(j = 0; j < n; j++) e[i][j] = -1;
for(i = 0; i < m; i++){
cin >> a >> b >> c;
e[a][b] = c;
e[b][a] = c;
}
min_d = 99999999;
dfs(c1, 0, 0);
cout << ans << " " << max_ << endl;
system("pause");
}
解法3:
#include <iostream>
#include <queue>
using namespace std;
int dis[1000];
int num[1000];
bool v[1000];
struct Node{
int t;
Node(){};
Node(int a)
{
t = a;
}
bool operator < (const Node &a)const{
return dis[t] > dis[a.t];
}
};
int main()
{
int n, m, c1, c2;
cin >> n >> m >> c1 >> c2;
int i, j;
int rt[1000];
int e[501][501];
for(i = 0; i < n; i++) cin >> rt[i];
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
e[i][j] = -1;
int a, b, c;
for(i = 0; i < m; i++){
cin >> a >> b >> c;
e[a][b] = c;
e[b][a] = c;
}
//spfa
int max[1000];
priority_queue<Node> q;
Node p;
int now;
for(i = 0; i < n; i++)
{
dis[i] = 99999999;
v[i] = false;
}
dis[c1] = 0;
max[c1] = rt[c1];
num[c1] = 1;
v[c1] = true;
q.push(c1);
while(!q.empty()){
p = q.top();
now = p.t;
q.pop();
for(i = 0; i < n; i++)
if(e[now][i] != -1 && dis[now] + e[now][i] < dis[i])
{
num[i] = num[now];
max[i] = max[now] + rt[i];
dis[i] = dis[now] + e[now][i];
if(!v[i])
{
q.push(i);
v[i] = true;
}
}
else if(e[now][i] != -1 && dis[now] + e[now][i] == dis[i])
{
num[i] += num[now];
if(max[i] < max[now] + rt[i])
max[i] = max[now] + rt[i];
if(!v[i])
{
q.push(i);
v[i] = true;
}
}
v[now] = false;
}
cout << num[c2] << " " << max[c2] << endl;
system("pause");
}