链接: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;
}