• AcWing 1128. 信使


    \(AcWing\) \(1128\). 信使

    题目传送门

    一、题目描述

    战争时期,前线有 \(n\) 个哨所,每个哨所可能会与其他若干个哨所之间有通信联系。

    信使负责在哨所之间传递信息,当然,这是要花费一定时间的(以天为单位)。

    指挥部设在 第一个 哨所。

    当指挥部下达一个命令后,指挥部就派出若干个信使向与指挥部相连的哨所送信。

    当一个哨所接到信后,这个哨所内的信使们也以同样的方式向其他哨所送信。信在一个哨所内停留的时间可以忽略不计。

    直至所有 \(n\) 个哨所全部接到命令后,送信才算成功。

    因为准备充足,每个哨所内都安排了足够的信使(如果一个哨所与其他 \(k\) 个哨所有通信联系的话,这个哨所内至少会配备 \(k\) 个信使)。

    现在总指挥请你编一个程序,计算出完成整个送信过程 最短需要多少时间

    输入格式
    \(1\) 行有两个整数 \(n\)\(m\),中间用 \(1\) 个空格隔开,分别表示有 \(n\) 个哨所和 \(m\) 条通信线路。

    \(2\)\(m+1\) 行:每行三个整数 \(i、j、k\),中间用 \(1\) 个空格隔开,表示第 \(i\) 个和第 \(j\) 个哨所之间存在 双向 通信线路,且这条线路要花费 \(k\) 天。

    输出格式
    一个整数,表示完成整个送信过程的最短时间。

    如果不是所有的哨所都能收到信,就输出\(-1\)

    二、题目解析

    • 单源最短路径,一般采用堆优化版本的\(Dijkstra\)算法
    • 最短距离的最大值,也就是 完成整个送信过程的最短时间

    三、\(Dijkstra+PII\)

    #include <bits/stdc++.h>
    using namespace std;
    typedef pair<int, int> PII;
    
    const int N = 110;
    const int M = 2 * 210; //无向边,开两倍
    
    int n, m;
    int h[N], e[M], w[M], ne[M], idx;
    void add(int a, int b, int c) {
        e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
    }
    int d[N];
    bool st[N];
    
    int dijkstra() {
        int res = 0, cnt = 0;
    
        //初始化为正无穷
        memset(d, 0x3f, sizeof d);
        d[1] = 0; // 1号点为出发点,距离为0
        //小顶堆
        priority_queue<PII, vector<PII>, greater<>> q;
        q.push({0, 1});
    
        while (q.size()) {
            auto u = q.top();
            q.pop();
    
            if (st[u.second]) continue; // Dijkstra第一次出队列为最小值
            st[u.second] = true;
    
            //求所有最短距离的最大值
            res = max(res, u.first);
            //记录到达的节点个数
            cnt++;
    
            for (int i = h[u.second]; ~i; i = ne[i]) {
                int j = e[i];
                if (d[j] > d[u.second] + w[i]) {
                    d[j] = d[u.second] + w[i];
                    q.push({d[j], j});
                }
            }
        }
        //如果可以成功到达每个节点,返回最短距离的最大值,否则返回-1
        return cnt == n ? res : -1;
    }
    int main() {
        //加快读入
        cin.tie(0), ios::sync_with_stdio(false);
    
        memset(h, -1, sizeof h);
        cin >> n >> m;
        while (m--) {
            int a, b, c;
            cin >> a >> b >> c;
            add(a, b, c), add(b, a, c);
        }
    
        printf("%d\n", dijkstra());
        return 0;
    }
    
    
    

    四、\(Dijkstra\)+结构体

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 110;
    const int M = 2 * 210; //无向边,开两倍
    
    int n, m;
    int h[N], e[M], w[M], ne[M], idx;
    void add(int a, int b, int c) {
        e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
    }
    int d[N];
    bool st[N];
    
    //定义结构体
    struct Node {
        int id;     //结点ID
        int dist;   //和起点的距离
        bool operator<(const Node &t) const {
            return dist > t.dist; //重载小于号,父节点距离 大于 孔洞节点 距离,则大元素向下,小元素向上,小顶堆
        }
    };
    
    int dijkstra() {
        int res = 0, cnt = 0;
    
        //初始化为无法到达
        memset(d, 0x3f, sizeof d);
        d[1] = 0; // 1号点为出发点,距离为0
    
        //小顶堆
        priority_queue<Node> q;
        q.push({1, 0});
    
        while (q.size()) {
            auto u = q.top();
            q.pop();
    
            if (st[u.id]) continue;
            st[u.id] = true;
    
            res = max(res, u.dist);
            cnt++; //出队列时统计个数
    
            //枚举每个出边
            for (int i = h[u.id]; ~i; i = ne[i]) {
                int j = e[i];
                if (d[j] > d[u.id] + w[i]) {
                    d[j] = d[u.id] + w[i];
                    q.push({j, d[j]});
                }
            }
        }
        return cnt == n ? res : -1;
    }
    int main() {
        //加快读入
        cin.tie(0), ios::sync_with_stdio(false);
        memset(h, -1, sizeof h);
        cin >> n >> m;
        while (m--) {
            int a, b, c;
            cin >> a >> b >> c;
            add(a, b, c), add(b, a, c);
        }
        printf("%d\n", dijkstra());
        return 0;
    }
    

    五、\(SPFA\)解法

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 110;
    const int M = 2 * 210; //无向边,开两倍
    const int INF = 0x3f3f3f3f;
    
    int n, m;
    int h[N], e[M], w[M], ne[M], idx;
    void add(int a, int b, int c) {
        e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
    }
    int d[N];
    bool st[N];
    
    //定义结构体
    struct Node {
        int id;   //节点ID
        int dist; //和起点的距离
        bool operator<(const Node &t) const {
            return dist > t.dist; //重载小于号,父节点距离 大于 孔洞节点 距离,则大元素向下,小元素向上,小顶堆
        }
    };
    
    // spfa模板
    void spfa() {
        queue<int> q;              //队列
        memset(d, 0x3f, sizeof d); //将所有距离初始化为无穷大
    
        //出发点的距离清零
        d[1] = 0;
    
        q.push(1);    //出发点入队列
        st[1] = true; //出发点标识已使用
        while (q.size()) {
            int u = q.front();
            q.pop();
            st[u] = false;
            for (int i = h[u]; ~i; i = ne[i]) {
                int j = e[i];
                if (d[j] > d[u] + w[i]) {
                    d[j] = d[u] + w[i];
                    if (!st[j]) {
                        st[j] = true;
                        q.push(j);
                    }
                }
            }
        }
    }
    
    // 14 ms
    int main() {
        //加快读入
        cin.tie(0), ios::sync_with_stdio(false);
        memset(h, -1, sizeof h);
        cin >> n >> m;
        while (m--) {
            int a, b, c;
            cin >> a >> b >> c;
            add(a, b, c), add(b, a, c);
        }
        spfa();
    
        int res = 0;
        for (int i = 2; i <= n; i++) {
            if (d[i] == INF) {
                res = -1;
                break;
            }
            res = max(res, d[i]);
        }
        printf("%d\n", res);
        return 0;
    }
    

    六、\(Floyd\)解法

    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 110;
    const int INF = 0x3f3f3f3f;
    
    int n, m;
    int d[N][N];
    
    //	45 ms
    int main() {
        //加快读入
        cin.tie(0), ios::sync_with_stdio(false);
    
        cin >> n >> m;
    
        //初始化邻接矩阵
        memset(d, 0x3f, sizeof d);
        for (int i = 1; i <= n; i++) d[i][i] = 0;
    
        while (m--) {
            int a, b, c;
            cin >> a >> b >> c;
            d[a][b] = d[b][a] = min(d[a][b], c);
        }
    
        // 5行代码的Floyd
        for (int k = 1; k <= n; k++)
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++)
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
    
        int res = 0;
        for (int i = 1; i <= n; i++)
            if (d[1][i] == INF) {
                res = -1;
                break;
            } else
                res = max(res, d[1][i]);
    
        printf("%d\n", res);
        return 0;
    }
    
  • 相关阅读:
    MySQL教程(四)—— MySQL的登录与退出
    MySQL教程(三)—— MySQL的安装与配置
    django中使用POST方法报错 URL via POST, but the URL doesn't end in a slash
    django的html模板中获取字典的值
    使用pycharm手动搭建python语言django开发环境(五) 使用日志模块打日志
    使用pycharm手动搭建python语言django开发环境(四) django中buffer类型与str类型的联合使用
    python语言 buffer类型数据的使用 'ascii' codec can't decode byte 0xe5 问题的解决
    使用pycharm手动搭建python语言django开发环境(三) 使用django的apps应用 添加应用静态文件
    使用pycharm手动搭建python语言django开发环境
    使用pycharm手动搭建python语言django开发环境(一)
  • 原文地址:https://www.cnblogs.com/littlehb/p/15999867.html
Copyright © 2020-2023  润新知