bzoj 1875 [SDOI2009]HH去散步 矩阵乘法

Posted copperoxide

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1875 [SDOI2009]HH去散步 矩阵乘法相关的知识,希望对你有一定的参考价值。

题面

题目传送门

解法

如果没有不能经过上一次经过的边这个限制,显然就是矩阵乘法的裸题

那么我们考虑转化一下,把边当成点

将一条无向边拆成2条有向边,然后连边,设邻接矩阵为(A)

(A)变成(A^{T-1}),然后枚举起点的出边,终点的入边即可

时间复杂度:(O(m^3 log T))

代码

#include <bits/stdc++.h>
#define Mod 45989
#define N 150
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == ‘-‘) f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - ‘0‘, c = getchar(); x *= f;
}
struct Node {
    int x, y;
} a[N];
struct Matrix {
    int a[N][N];
    void Clear() {memset(a, 0, sizeof(a));}
};
int n, m, T, s, t, tot, cnt;
vector <int> e[N];
Matrix operator * (Matrix x, Matrix y) {
    Matrix ret; ret.Clear();
    for (int k = 2; k <= tot; k++)
        for (int i = 2; i <= tot; i++)
            for (int j = 2; j <= tot; j++)
                ret.a[i][j] = (ret.a[i][j] + x.a[i][k] * y.a[k][j] % Mod) % Mod;
    return ret;
}
Matrix operator ^ (Matrix x, int y) {
    Matrix ret = x; y--;
    while (y) {
        if (y & 1) ret = ret * x;
        y >>= 1, x = x * x;
    }
    return ret;
}
int main() {
    read(n), read(m), read(T), read(s), read(t);
    s++, t++, tot = 1;
    for (int i = 1; i <= m; i++) {
        int x, y; read(x), read(y);
        a[++tot] = (Node) {++x, ++y};
        a[++tot] = (Node) {y, x};
        e[x].push_back(tot - 1), e[x].push_back(tot);
        e[y].push_back(tot - 1), e[y].push_back(tot);
    }
    Matrix tx; tx.Clear();
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < e[i].size(); j++)
            for (int k = 0; k < e[i].size(); k++) {
                int x = e[i][j], y = e[i][k];
                if (x == y || (x ^ 1) == y) continue;
                if (a[x].y == a[y].x) tx.a[x][y] = 1;
            }
    tx = tx ^ (T - 1); int ans = 0;
    for (int i = 2; i <= tot; i++)
        for (int j = 2; j <= tot; j++)
            if (a[i].x == s && a[j].y == t) ans = (ans + tx.a[i][j]) % Mod;
    cout << ans << "
";
    return 0;
}

以上是关于bzoj 1875 [SDOI2009]HH去散步 矩阵乘法的主要内容,如果未能解决你的问题,请参考以下文章

BZOj-1875: [SDOI2009]HH去散步 (矩阵快速幂)

bzoj 1875: [SDOI2009]HH去散步 -- 矩阵乘法

BZOJ 1875SDOI 2009HH去散步

BZOJ_1875_[SDOI2009]HH去散步_矩阵乘法

bzoj 1875 [SDOI2009]HH去散步(矩乘)

bzoj1875 [SDOI2009]HH去散步——矩阵快速幂