利用Dijkstra最短路算法,用totalWeight
记录到达某个城市时最多能搜集的救援队数,用dist
表示当前到达某个城市的最短距离;用pre
记录某一城市的前驱结点,即从哪个城市来。最后用dfs数出最短路数。
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int inf = 0x7fffffff;
int cityNum, roadNum, source, dest;
int weight[500]; //rescure team in each city
int map[500][500];
int dist[500]; //minimum distance to each city
int totalWeight[500]; //max rescure team gathered to a city
bool visited[500];
vector<int> pre[500]; //come from which cities
int pathNum = 0;
void countPath(int cur) {
if (cur == source) {
pathNum++;
return;
}
for (int i = 0;i < pre[cur].size();i++) {
countPath(pre[cur][i]);
}
}
int main() {
fill(map[0], map[0] + 500 * 500, inf);
fill(totalWeight, totalWeight + 500, 0);
fill(dist, dist + 500, inf);
scanf("%d %d %d %d", &cityNum, &roadNum, &source, &dest);
for (int i = 0;i < cityNum;i++) {
scanf("%d", &weight[i]);
}
for (int i = 0;i < roadNum;i++) {
int v1, v2, len;
scanf("%d %d %d", &v1, &v2, &len);
map[v1][v2] = len;
map[v2][v1] = len;
}
dist[source] = 0;
totalWeight[source] = weight[source];
for (int i = 0;i < cityNum;i++) {
int u = -1, minDis = inf;
for (int j = 0;j < cityNum;j++) {
if (!visited[j] && dist[j] < minDis) {
u = j;
minDis = dist[j];
}
}
if (u == -1 || u == dest)
break;
visited[u] = true;
for (int v = 0;v < cityNum;v++) {
if (!visited[v] && map[u][v] != inf) {
if (dist[u] + map[u][v] < dist[v]) {
dist[v] = dist[u] + map[u][v];
totalWeight[v] = totalWeight[u] + weight[v];
pre[v].push_back(u);
}
else if (dist[u] + map[u][v] == dist[v]) {
pre[v].push_back(u);
totalWeight[v] = max(totalWeight[v], weight[v] + totalWeight[u]);
}
}
}
}
countPath(dest);
printf("%d %d", pathNum, totalWeight[dest]);
}