考察最短路径 Dijkstra算法
题目大意:给出N个城市,M条无向边,每个城市都有一定的救援小组,所有边的边权(两城市之间的距离),所有城市的点权(每个城市拥有的救援小组的个数)已知,给起点和终点,求起点和终点的最短路径以及最短路径上救援小组的数目之和,如果有多条最短路径,则输出数目之和最大的。
思路:考虑Dijkstra+DFS的方法[算法笔记]最短路径 Dijkstra算法
即第一标尺是求最短路径,第二标尺是求点权之和最大的路径
在第二标尺计算中选择最大的路径。
for (int i = tempPath.size() - 1; i >= 0; i--) {
int id = tempPath[i];
tempw += weight[id];
}
if (tempw > maxw) {
maxw = tempw;
path = tempPath;
}
AC代码
//1003 Emergency (25 分)
#include<cstdio>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXV = 510;
const int INF = 1000000000;
int n, m, st, ed, G[MAXV][MAXV], weight[MAXV], d[MAXV];
int numPath = 0;//路径条数
int maxw = 0;//最大点权
bool vis[MAXV] = { false };
vector<int>pre[MAXV];
vector<int>tempPath, path;
void Dijkstra(int s) {
fill(d, d + MAXV, INF);
d[s] = 0;
for (int i = 0; i < n; i++) {
int u = -1, MIN = INF;
for (int j = 0; j < n; j++) {
if (vis[j] == false && d[j] < MIN) {
MIN = d[j];
u = j;
}
}
if (u == -1)return;
vis[u] = true;
for (int v = 0; v < n; v++) {
if (vis[v] == false && G[u][v] != INF) {
if (d[v] > G[u][v] + d[u]) {
d[v] = G[u][v] + d[u];
pre[v].clear();
pre[v].push_back(u);
}
else if (d[v] == G[u][v] + d[u])pre[v].push_back(u);
}
}
}
}
void DFS(int v) {
if (v == st) {
//递归边界
numPath++;
int tempw = 0;
tempPath.push_back(v);
for (int i = tempPath.size() - 1; i >= 0; i--) {
int id = tempPath[i];
tempw += weight[id];
}
if (tempw > maxw) {
maxw = tempw;
path = tempPath;
}
tempPath.pop_back();
return;
}
tempPath.push_back(v);
for (int i = 0; i < pre[v].size(); i++) {
DFS(pre[v][i]);
}
tempPath.pop_back();
}
int main() {
(void)scanf("%d %d %d %d", &n, &m, &st, &ed);
for (int i = 0; i < n; i++) {
scanf("%d", &weight[i]);
}
int u, v;
fill(G[0], G[0] + MAXV * MAXV, INF);
for (int i = 0; i < m; i++) {
scanf("%d %d", &u, &v);
scanf("%d", &G[u][v]);
G[v][u] = G[u][v];
}
Dijkstra(st);
DFS(ed);
printf("%d %d\n", numPath, maxw);
return 0;
}