【ACWing】1128. 信使

题目地址:

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 1n100
1 ≤ m ≤ 200 1≤m≤200 1m200
1 ≤ k ≤ 1000 1≤k≤1000 1k1000

实际就是求以 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)

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/115110131
今日推荐