L2-001 紧急救援 (25 分)
求带点权的最短路
Dijkstra算法
用Dijkstra跑一边,跑的时候如果是最短路的话就多判断一下点权即可,然后记录一下路径条数。
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1010;
int n, m, s, d;
int f[N]; // 救援队数量
int map[N][N]; // Dijkstra-初始值-边的长度
bool st[N]; // Dijkstra-这个点是否已经确定
int pre[N]; // 这个点的前置点
int t[N]; // 初始值-救援队数量
int dist[N]; // Dijkstra-到起点距离
int num[N]; // 相同路个数
int main()
{
memset(map, 0x3f, sizeof map);
cin >> n >> m >> s >> d;
for (int i = 0; i < n; i++)
{
cin >> t[i];
}
for (int i = 1; i <= m; i++)
{
int a, b, c;
cin >> a >> b >> c;
map[a][b] = map[b][a] = c;
}
memset(dist, 0x3f, sizeof dist);
dist[s] = 0;
f[s] = t[s];
num[s] = 1;
for (int i = 0; i < n; i++)
{
int u = -1;
for (int j = 0; j < n; j++)
{
if (st[j])
continue;
if (u == -1 || dist[u] > dist[j])
{
u = j;
}
}
st[u] = true;
for (int j = 0; j < n; j++)
{
if (st[j])
continue;
if (dist[j] == dist[u] + map[u][j])
{
if (f[j] < f[u] + t[j])
{
pre[j] = u;
f[j] = f[u] + t[j];
}
num[j] += num[u];
}
else if (dist[j] > dist[u] + map[u][j])
{
dist[j] = dist[u] + map[u][j];
f[j] = f[u] + t[j];
pre[j] = u;
num[j] = num[u];
}
}
}
cout << num[d] << ' ' << f[d] << endl;
int sta[N];
int tt = -1;
int u = d;
while (u != s)
{
sta[++tt] = u;
u = pre[u];
}
sta[++tt] = u;
while (tt)
{
cout << sta[tt--] << ' ';
}
cout << sta[0] << endl;
return 0;
}
测试点2
需要注意最短路径条数的继承。