当边权均为0或1时,我们是num[i][j][t]表示从i点到j点时间为t的方案数,将t拿出来,用矩阵快速幂进行优化,使得复杂度由O(Tn^3)变为O(logT n^3)。
那么现在对于边权不同的图怎么办呢?
我们将一个点拆为9个点来做。如果点i到点j有一条k的边,那么我们就连一条(i,k)到(j,1)的边。
而对于每个点拆成的9个点,在相邻两点之间进行连边。
最后,将矩阵累乘T次,用矩阵快速幂优化即可。
#include <bits/stdc++.h>
using namespace std;
const int MOD=2e3+9;
int n,t,m;
char str[21];
struct number{int num[201][201];}a,ans;
inline number mul(number a,number b)
{
number c;
for (register int i=1; i<=n; ++i)
for (register int j=1; j<=n; ++j) c.num[i][j]=0;
for (register int i=1; i<=n; ++i)
for (register int j=1; j<=n; ++j)
for (register int k=1; k<=n; ++k)
c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
return c;
}
inline void pow(int k)
{
while (k)
{
if (k&1) ans=mul(ans,a);
a=mul(a,a);
k>>=1;
}
}
int main(){
scanf("%d%d",&n,&t);
m=n; n*=9;
for (register int i=1; i<=m; ++i)
for (register int j=1; j<=8; ++j)
a.num[9*(i-1)+j][9*(i-1)+j+1]=1;
for (register int i=1; i<=m; ++i)
{
scanf("%s",str+1);
for (register int j=1; j<=m; ++j)
if (str[j]>'0') a.num[9*(i-1)+str[j]-'0'][9*(j-1)+1]=1;
}
for (register int i=1; i<=n; ++i) ans.num[i][i]=1;
pow(t);
printf("%d\n",ans.num[1][9*(m-1)+1]);
return 0;
}