题目地址:
https://www.acwing.com/problem/content/1130/
战争时期,前线有 n n n个哨所,每个哨所可能会与其他若干个哨所之间有通信联系。信使负责在哨所之间传递信息,当然,这是要花费一定时间的(以天为单位)。指挥部设在第一个哨所。当指挥部下达一个命令后,指挥部就派出若干个信使向与指挥部相连的哨所送信。当一个哨所接到信后,这个哨所内的信使们也以同样的方式向其他哨所送信。信在一个哨所内停留的时间可以忽略不计。直至所有 n n n个哨所全部接到命令后,送信才算成功。因为准备充足,每个哨所内都安排了足够的信使(如果一个哨所与其他 k k k个哨所有通信联系的话,这个哨所内至少会配备 k k k个信使)。现在总指挥请你编一个程序,计算出完成整个送信过程最短需要多少时间。
输入格式:
第 1 1 1行有两个整数 n n n和 m m m,中间用 1 1 1个空格隔开,分别表示有 n n n个哨所和 m m m条通信线路。第 2 2 2至 m + 1 m+1 m+1行:每行三个整数 i i i、 j j j、 k k k,中间用 1 1 1个空格隔开,表示第 i i i个和第 j j j个哨所之间存在双向通信线路,且这条线路要花费 k k k天。
输出格式:
一个整数,表示完成整个送信过程的最短时间。如果不是所有的哨所都能收到信,就输出 − 1 -1 −1。
数据范围:
1 ≤ n ≤ 100 1≤n≤100 1≤n≤100
1 ≤ m ≤ 200 1≤m≤200 1≤m≤200
1 ≤ k ≤ 1000 1≤k≤1000 1≤k≤1000
实际就是求以 1 1 1号点为源点的单源最短路,找到最短路最长的终点即可。如果有点到不了则输出 − 1 -1 −1。可以用SPFA来做,参考https://blog.csdn.net/qq_46105170/article/details/113821633。代码如下:
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 110;
int n, m;
int g[N][N], dis[N];
bool st[N];
void spfa() {
memset(dis, 0x3f, sizeof dis);
dis[1] = 0;
queue<int> q;
q.push(1);
while (q.size()) {
int t = q.front();
q.pop();
st[t] = false;
for (int i = 1; i <= n; i++) {
if (dis[i] > dis[t] + g[t][i]) {
dis[i] = dis[t] + g[t][i];
if (!st[i]) {
q.push(i);
st[i] = true;
}
}
}
}
}
int main() {
cin >> n >> m;
memset(g, 0x3f, sizeof g);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
g[a][b] = g[b][a] = min(g[a][b], c);
}
spfa();
int res = 0;
for (int i = 1; i <= n; i++)
res = max(res, dis[i]);
cout << (res == 0x3f3f3f3f ? -1 : res) << endl;
return 0;
}
时间复杂度 O ( n m ) O(nm) O(nm)(但实际要比这个快很多),空间 O ( n 2 ) O(n^2) O(n2)。