题目地址:
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)。