城市间紧急救援
这是一道由迪杰斯塔拉算法和动态规划相结合的题目。
题目大意:作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
用迪杰斯特拉算法找到最短路径,用动态规划来维护两个分别代表路径和人数的数组。
我这里用数组peo来代表到每个点最大的人数,用Count数组来代表到每个点最大的路径总数。
状态的转移可以被分成两种情况:
第一.
if (dis[t] + mp[t][k] < dis[k])
{
dis[k] = dis[t] + mp[t][k];
path[k] = t;
Count[k] = Count[t];
peo[k] = ph[k] + peo[t];
}
从当前节点t到未访问的节点k的距离小于目前到达k点的最小距离,那么距离更新这个最短距离,到达k节点的上一个节点为t,到达k节点的路径总数就是到达节点t的路径总数(因为到达k节点就要先到达节点t,而从节点t到达节点k就只有一条路)。到达k节点的人数为k节点的人数加上原有的人数。
第二.
else if (dis[t] + mp[t][k] == dis[k])
{
Count[k] += Count[t];
if (peo[k] < ph[k] + peo[t])
{
peo[k] = ph[k] + peo[t];
path[k] = t;
}
}
从当前节点t到未访问的节点k的距离等于目前到达k点的最小距离,那么到达节点k的路径总数就是原有的到达节点k的路径总数加上从节点t到达节点k的路径总数。在这种情况下,如果从节点t到达节点k,所能携带的人数多余当前到达k节点的最大人数,那么就更新k的上一个节点为t。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int M = 1000;
const int INF = 0x3f3f3f3f;
int mp[M][M], path[M], ph[M], peo[M], dis[M], Count[M];//path存储该点的上一个点,ph存储每个点的人数,peo存储到达该点时的 //最大人数,dis存储从当前点到达该点的最短距离,Count存储到达该点的 //最短路径数
int n, m, s, d;
bool vis[M] = { false };
void Dijkstra()
{
dis[s] = 0;
Count[s] = 1;
peo[s] = ph[s];
for (int i = 0; i < n; i++)
{
int t = -1, min_n = INF;
for (int j = 0; j < n; j++)
{
if (dis[j] < min_n && !vis[j])
{
min_n = dis[j];
t = j;
}
}//该循环找出当前所有未被访问的点中的最短距离
if (t == -1)
break;//表示所有点都已被访问
vis[t] = true;
for (int k = 0; k < n; k++)
{
if (dis[t] + mp[t][k] < dis[k])
{
dis[k] = dis[t] + mp[t][k];
path[k] = t;
Count[k] = Count[t];
peo[k] = ph[k] + peo[t];
}
else if (dis[t] + mp[t][k] == dis[k])
{
Count[k] += Count[t];
if (peo[k] < ph[k] + peo[t])
{
peo[k] = ph[k] + peo[t];
path[k] = t;
}
}
}
}
}
void print(int x)
{
if (path[x] != -1)
{
print(path[x]);
cout << path[x] << " ";
}
}
int main()
{
cin >> n >> m >> s >> d;
memset(mp, INF, sizeof mp);
memset(path, -1, sizeof path);
memset(dis, INF, sizeof dis);
for (int i = 0; i < n; i++)Count[i] = 1;
for (int i = 0; i < n; i++) cin >> ph[i];
for (int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
mp[a][b] = mp[b][a] = c;
}
Dijkstra();
cout << Count[d] << " " << peo[d] << endl;
print(d);
cout << d << endl;
return 0;
}