题目链接:
题目表述:
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, 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
思路:
1. 最短路Dijkstra, 求最短路条件下的最大点权。
2. 就是给出一个无向图的边权和点权,判断从c1到c2的最短路径,以及在最短路径的前提下找出最大点权。
3. 用Dijkstra先求最短路,求最短路过程中同时求出最大点权
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 505, inf = 0x3f3f3f3f;
//G为邻接矩阵,w点权,即每个城市的队伍, maxT最多能聚集的队伍, d到目的城市的最短距离, num最短路数量
int G[maxn][maxn], w[maxn], maxT[maxn], d[maxn], num[maxn];
int n, m, c1, c2;
bool vis[maxn]; //判断是否访问过该城市
void Dijkstra(int s){
fill(d, d+maxn, inf); //初始化最短距离
d[s] = 0; //到自身的最短距离为0
maxT[s] = w[s]; //初始队伍数为自己的点权
num[s] = 1; //初始最短路只有1条
for(int i = 0; i < n; i++){ //遍历n个城市
int MIN = inf, u = -1;
for(int j = 0; j < n; j++){ // 查找未访问过的城市中距离最小的
if(!vis[j] && d[j] < MIN){
u = j;
MIN = d[j];
}
}
if(u == -1) return; // 未找到直接返回
vis[u] = true; // 标记当前访问的城市
for(int j = 0; j < n; j++){
if(!vis[j] && G[u][j]){ // 查找能直接到达的未访问过的城市
if(d[u] + G[u][j] < d[j]){ //如果从u到v的最短距离可以优化
// 更新距离和最大权值, 最短路条数不变
d[j] = d[u] +G[u][j];
maxT[j] = maxT[u] + w[j];
num[j] = num[u];
}else if(d[u] + G[u][j] == d[j]){ //最短路不唯一
// 如果找到相同的最短距离,最短路条数累加
if(maxT[u] + w[j] > maxT[j]){ // 如果总权值更大,则更新最大权值
maxT[j] = maxT[u] + w[j];
}
num[j] += num[u];
}
}
}
}
}
int main(){
cin >> n >> m >> c1 >> c2;
for(int i = 0; i < n; i++){
cin >> w[i];
}
for(int i = 0; i < m; i++){
int a, b, c;
cin >> a >> b >> c;
G[a][b] = G[b][a] = c;
}
Dijkstra(c1);
printf("%d %d",num[c2], maxT[c2]); // 输出
return 0;
}