• POJ 3613 Cow Relays(Floyd + 矩阵运算)


    题意:

    求 s 到 e 且经过 n 条边的最短路径。

    思路:

    1. Floyd 算法在维基百科上面有详细的介绍:https://zh.wikipedia.org/zh-cn/%E5%BC%97%E6%B4%9B%E4%BC%8A%E5%BE%B7%E7%AE%97%E6%B3%95

    2. O(n3) 的算法一次性把结果求到位了,而不知道中间经历了多少边。而本题矩阵的解法则是“放慢”了的 floyd

    3. Floyd 算法相当于利用二维的空间解决三维的问题,这点和 01 背包差不多。而代码中的每次矩阵相乘,实际上只是要多找一个边

    4. 这里的单位矩阵 M2 也是和 E 有点出入的,具体就看代码吧。

    #include <iostream>
    #include <algorithm>
    #include <map>
    using namespace std;
    
    const int MAXN = 210;
    
    class Matrix {
    public:
        int e[MAXN][MAXN], n;
    
        void setn(int n) { this->n = n; }
        void initvalue() { memset(e, 0x3F, sizeof(e)); }
    
        Matrix operator = (const Matrix& o) {
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++) 
                    e[i][j] = o.e[i][j];
            return *this;
        }
        Matrix operator * (const Matrix& o) {
            Matrix m;
            m.initvalue();
            for (int k = 1; k <= n; k++)
                for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++)
                    m.e[i][j] = min(m.e[i][j], e[i][k] + o.e[k][j]);
            return m;
        }
    };
    
    Matrix M1, M2;
    map<int, int> my;
    
    int main() {
        int n, t, s, e;
        while (~scanf("%d%d%d%d", &n, &t, &s, &e)) {
            int cflag = 0;
            M1.initvalue(); 
            M2.initvalue();
            for (int i = 0; i < t; i++) {
                int cost, u, v;
                scanf("%d%d%d", &cost, &u, &v);
                if (!my[u]) my[u] = ++cflag;
                if (!my[v]) my[v] = ++cflag;
                int a = my[u], b = my[v];
                M1.e[a][b] = M1.e[b][a] = cost;
            }
            for (int i = 1; i <= cflag; i++)
                M2.e[i][i] = 0;
    
            M1.setn(cflag), M2.setn(cflag);
    
            while (n) {
                if (n & 1)
                    M2 = M1 * M2;
                M1 = M1 * M1;
                n >>= 1;
            }
    
            printf("%d\n", M2.e[my[s]][my[e]]);
        }
        return 0;
    }
    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    无重叠区间
    ARC109E 1D Reversi Builder
    IOI2021集训队作业129CF Longest Rivers
    IOI2021集训队作业281CA Balanced Diet
    IOI2021集训队作业227CB Branch Assignment
    IOI2021集训队作业277BK Tours
    IOI2021集训队作业125AA Baggage
    6894. 【2020.11.25提高组模拟】小 S 埋地雷 (loj6611. 摧毁时间线)
    ARC108 题解&总结
    HTML教程
  • 原文地址:https://www.cnblogs.com/kedebug/p/3049148.html
Copyright © 2020-2023  润新知