原题链接PTA | 程序设计类实验辅助教学平台 (pintia.cn)
Acwing链接1475. 紧急情况 - AcWing题库
分析
0.易错点
for(int j = 0; j < n; j ++ )
{
if(dist[j] > dist[t] + g[t][j])
{
dist[j] = dist[t] + g[t][j];
cnt[j] = cnt[t];
//sum[j] += sum[t]; sum[j] += sum[t] + w[j];
// 这样是错的,救援队的数量没有加上j点本身的救援队数量
sum[j] = sum[t] + w[j]; // 这一步易出错
}
else if(dist[j] == dist[t] + g[t][j])
{
cnt[j] += cnt[t];
sum[j] = max(sum[j], sum[t] + w[j]);
}
}
1. 准备
const int N = 600;
int g[N][N], w[N]; // w[N]指权值, 这里是指每个点救援队的数量
int dist[N], cnt[N], sum[N]; //cnt[N] 最短路的数 sum[N]聚集到的救援队的最大数量
bool st[N];
int n, m, Start, End;// 点数 边数 当前救援起点城市编号 发出救援信号的城市编号
2. 核心
void dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[Start] = 0, cnt[Start] = 1, sum[Start] = w[Start];
// dist[S] 起点到起点的距离为 0
// cnt[S] = 1 题目数据保证 C1 和 C2 之间至少存在一条路径相连。
// sum[S] = w[S] 最大救援队数量
// 这里救援队还没出发去其他城市 所以救援队数量只有S号城市的救援队
for(int i = 0; i < n; i ++)
{
int t = -1;
for(int j = 0; j < n; j ++ )
{
if(st[j] == false && (t == -1 || dist[t] > dist[j]) ) t = j;
}
st[t] = true;
// 用t 更新每个点到起点的距离
for(int j = 0; j < n; j ++ ) // j 从0 开始 因为城市编号是从0开始的
{
if(dist[j] > dist[t] + g[t][j]) //从t点中转 j 先到t t再到起点
{
dist[j] = dist[t] + g[t][j];
cnt[j] = cnt[t];
sum[j] = sum[t] + w[j];
// 从t点中转时 总的救援队数量 sum[t] + j点的救援队数量
}
//从j点到起点的距离 和 从j到t再到起点的距离相等
else if(dist[j] == dist[t] + g[t][j])
{
cnt[j] += cnt[t]; // 最短路的个数
// 比较 到底是j点救援队数量多 还是 j到t中转再到起点时 救援队数量多
sum[j] = max(sum[j], sum[t] + w[j]);
}
}
}
}
3. main函数
int main()
{
memset(g, 0x3f, sizeof g);
cin >> n >> m >> Start >> End; // 输入
for(int i = 0; i < n; i ++ )
{
cin >> w[i]; // 输入权值——即每个点的救援队数量
}
while(m -- ) // m条边 所以次个输入
{
int a, b, c;
cin >> a >> b >> c;
g[a][b] = g[b][a] = min(g[a][b], c); // 邻接矩阵构造无向图
}
dijkstra();
cout << cnt[End] << ' ' << sum[End]; // 输出最短路数量 最大救援队数量
return 0;
}
4. AC代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 600;
int g[N][N];
int dist[N], cnt[N], sum[N], w[N];
int n, m, Start, End;
bool st[N];
void dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[Start] = 0, cnt[Start] = 1, sum[Start] = w[Start];
for(int i = 0; i < n; i ++ )
{
int t = -1;
for(int j = 0; j < n; j ++ )
{
if(st[j] == false && (t == -1 || dist[t] > dist[j]) )
t = j;
}
st[t] = true;
for(int j = 0; j < n; j ++ )
{
if(dist[j] > dist[t] + g[t][j])
{
dist[j] = dist[t] + g[t][j];
cnt[j] = cnt[t];
sum[j] = sum[t] + w[j];
}
else if(dist[j] == dist[t] + g[t][j])
{
cnt[j] += cnt[t];
sum[j] = max(sum[j], sum[t] + w[j]);
}
}
}
}
int main()
{
memset(g, 0x3f, sizeof g);
cin >> n >> m >> Start >> End;
for(int i = 0; i < n; i ++ )
{
cin >> w[i];
}
while(m -- )
{
int a, b, c;
cin >> a >> b >> c;
g[a][b] = g[b][a] = min(g[a][b], c);
}
dijkstra();
cout << cnt[End] << ' ' << sum[End];
return 0;
}