题解:
矩阵表示第一天的时候u到v有多少条路径,然后直接做矩阵k次幂就能得到k天从u到v的路径数,最后统计一下就可以了。
矩阵相乘的解释:
矩阵相乘,两矩阵必定行数或列数相等,然后第一个矩阵某行的各个元素分别乘第二个矩阵相应的列上的元素再相加。
想想,每个矩阵中的每个点都标识这个图中第i个点和第j个点之间有没有临接边
在矩阵乘法时,两矩阵点对应为:(i, k)和 (k, j),彼此之间以k为联通,而k也是两相乘的图中切实存在的一个点。
放到邻接矩阵相乘的过程中,即为第i点经过一个点(k为点集)到第j点总共有多少条路径。
同理,当问题改为AAA时,因为AA过程中存在一点k为中介点,AA得到的矩阵再乘A的过程中又会再有一个中介点。答案又会改为从i点走三步到j点总共有几条路径。
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define pb push_back
#define Rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
typedef long double ld;
const int inf=0x3f3f3f3f;
const ll INF=9e18;
const int N=1e2+50;
const ll mod=1e9+7;
int n,m,k,s;
struct Matrix{
ll a[N][N];
Matrix() { memset(a,0,sizeof(a)); }
Matrix operator* (const Matrix &rhs) const {
Matrix res;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
res.a[i][j]=(res.a[i][j]+a[i][k]*rhs.a[k][j])%mod;
return res;
}
}G,res;
void fpow(int k) {
while(k) {
if(k&1) res=res*G;
G=G*G;
k>>=1;
}
}
int main() {
scanf("%d%d%d%d",&n,&m,&k,&s);
for(int i=1;i<=m;i++) {
int u,v;
scanf("%d%d",&u,&v);
G.a[u][v]++;
}
for(int i=1;i<=n;i++) res.a[i][i]=1;
fpow(k);
ll sum=0;
for(int i=1;i<=n;i++)
if(i!=s) sum+=res.a[s][i],sum%=mod;
printf("%lld\n",sum);
return 0;
}