链接:https://ac.nowcoder.com/acm/contest/549/E
来源:牛客网

小A来到了一个陌生的城镇,这个城镇与其它城镇之间构成了集群。城镇之间的路径都是单向的,而小A每一天都能由一个城镇走到另外一个城镇。小A将会连续走k天,直到抵达某个城镇。也许他并不能走到这个城镇,那么可以认为不存在这样的路径,也就是路径数为0。否则就会有若干条路径可以抵达某个城镇。现在他想知道,如果他从给定某个城市出发,k天之后到达其它城镇的路径的总和是多少。数据不保证没有重边,也就是说可能每一天从一个城镇到另外一个城镇之间会有多条路径。路径总和可能会非常大,对答案模上1000000007。

思路:矩阵表示第一天的时候u到v有多少条路径,然后直接做矩阵k次幂就能得到k天从u到v的路径数,最后统计一下就可以了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 105;
ll mp[maxn + 5][maxn + 5];
ll Ans[maxn + 5][maxn + 5];
const ll mod = 1e9 + 7;
 
void qpow(ll a[maxn + 5][maxn+5], ll b[maxn+5][maxn+5], ll n) {
    int c[maxn+5][maxn+5];
    for(ll i = 1; i <= n; i++) {
        for(ll j = 1; j <= n; j++) {
            c[i][j] = 0;
            for(int k = 1; k <= n; k++) {
                c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % mod;
            }
        }
    }
    for(ll i = 1; i <= n; i++) {
        for(ll j = 1; j <= n; j++) {
            a[i][j] = c[i][j];
        }
    }
}
 
int main() {
    ll n, m, s, k;
    ll u, v;
    scanf("%lld%lld%lld%lld", &n, &m, &k, &s);
    for(ll i = 1; i <= m; i++) {
        scanf("%lld%lld", &u, &v);
        mp[u][v] += 1;
    }
    for(ll i = 1; i <= n; i++) {
        Ans[i][i] = 1;
    }
    while(k) {
        if(k&1) {
            qpow(Ans, mp, n);
        }
        qpow(mp, mp, n);
        k >>= 1;
    }
    long long ans = 0;
    for (int i = 1; i <= n; i++) {
        if (i == s) {
            continue;
        }
        ans += Ans[s][i];
        ans %= mod;
    }
    printf("%lld\n", ans);
    return 0;
}