\(Description:\)
给出一张图,求\(A->B\),经过t的时间之后的方案数,答案对45989取模。
但不能\(a->b\),马上,\(b->a\)
\(Sample\) \(Input\):
4 5 3 0 0
0 1
0 2
0 3
2 1
3 2
\(Sample\) \(Output:\)
4
\(Solution:\)
很明显这题是矩乘,但不知道怎么管那个限制条件。
这又是套路题。。。
考虑边是不会走反的,那么把边变成矩阵的点,这样就可以保障不会走反。
那么只有在两条边中一条边的终点为另一条起点时才可以连
然后一开始要强制走到A,做t-1次幂。
再把强制走的矩阵乘上去,最后统计终点为B的边的答案。
#pragma GCC optimize("inline")
#include<cstdio>
#include<iostream>
#include<cstring>
#define int long long
#define one first
#define two second
using namespace std;
int n,m,t,A,B,En,cnt,ans;
const int N=120*2,p=45989;
pair<int,int> E[N+5];
struct matrix {
int n,m;
int a[N+5][N+5];
inline void clear() { n=m=0;memset(a,0,sizeof(a));}
inline void set(int nx) { n=m=nx;for(int i=1;i<=nx;++i) a[i][i]=1;}
inline void write() const{
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j) cout<<a[i][j]<<" ";
cout<<endl;
}
putchar('\n');
}
inline matrix operator * (const matrix &nt) const {
matrix tmp;tmp.clear();
tmp.n=n;tmp.m=nt.m;
for(int i=1;i<=n;++i) for(int j=1;j<=nt.m;++j) for(int k=1;k<=m;++k)
tmp.a[i][j]=(tmp.a[i][j]+a[i][k]*nt.a[k][j]%p)%p;
return tmp;
}
inline matrix operator *= (const matrix &nt) { return (*this)=(*this)*nt;}
}a,b;
inline matrix power(matrix x,int b){
matrix ret;ret.clear();
ret.set(x.n);
while(b>0){
if(b&1) ret=ret*x;
x=x*x;
b>>=1;
}
return ret;
}
signed main(){
if(fopen("desire.in","r")){
freopen("desire.in","r",stdin);
freopen("desire.out","w",stdout);
}
ios::sync_with_stdio(0);
cin>>n>>m>>t>>A>>B;
for(int i=1;i<=m;++i){
int u=0,v=0;
cin>>u>>v;
E[++En]=make_pair(u,v);
E[++En]=make_pair(v,u);
}
a.n=1;a.m=En;
b.n=En;b.m=En;
for(int i=1;i<=En;++i) for(int j=1;j<=En;++j){
if(((i&1) && i+1==j) || (!(i&1) && i-1==j) || i==j) continue;
if(E[i].two==E[j].one) b.a[i][j]=1;
}
for(int i=1;i<=En;++i) if(E[i].one==A) a.a[1][i]=1;
a=a*power(b,t-1);
for(int i=1;i<=En;++i) if(E[i].two==B) ans=(ans+a.a[1][i])%p;
cout<<ans<<endl;
return 0;
}