一眼就能看出的矩阵加速,但是需要进行转换,主要在于题目中的不能马上走刚刚通过的路,所以有特殊的处理,无向边变有向边,边变点做矩阵加速。
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#define MAXN 400
const int mod = 45989;
using namespace std;
int N,M,T,A,B;
struct mat{
int n,m;
int t[MAXN +10][MAXN +10];
void init_min(){memset(t,0,sizeof(t));}
void init_max(){memset(t,0x3f,sizeof(t));}
void init_e()
{
memset(t,0,sizeof(t));
for(int i = 0;i < MAXN;i++)
t[i][i] = 1;
}
mat operator *(const mat &a)
{
mat c;
c.init_min();
c.n = n;
c.m = a.m;
for(int i = 0;i < n;i++)
for(int j = 0;j < a.n;j++)
for(int k = 0;k < a.m;k++)
c.t[i][k] = (c.t[i][k] + t[i][j] * a.t[j][k]) % mod;
return c;
}
};
mat map;
mat pow(mat a,int k)
{
mat ans;
ans.init_e();
ans.n = a.n;
ans.m = a.m;
while(k)
{
if(k&1)
ans = ans * a;
a = a * a;
k >>= 1;
}
return ans;
}
vector<pair<int,int> >Edges;
void pre()//边连边的初始化处理
{
int i,j;
for(i = 0; i < Edges.size(); i++)
for(j = 0; j < Edges.size(); j++)
if(Edges[i].second == Edges[j].first && (j ^ 1) != i)
map.t[i][j]++;
}
int main()
{
int i,j,k;
int u,v;
scanf("%d%d%d%d%d",&N,&M,&T,&A,&B);
for(i = 0;i < M;i++){
scanf("%d%d",&u,&v);
Edges.push_back(make_pair(u, v));
Edges.push_back(make_pair(v, u));
}
pre();
map.n = map.m = M * 2;
mat tt;
tt = pow(map,T - 1);
int ans = 0;
for(int i = 0; i < Edges.size(); i++) if(Edges[i].first == A)
for(int j = 0; j < Edges.size(); j++) if(Edges[j].second == B)
ans = (ans + tt.t[i][j]) % mod;
printf("%d\n",ans);
}