对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。
对于100%的数据,N ≤ 20,M ≤ 60,t ≤ 230,0 ≤ A,B<n,0 ≤="" ai,bi="" <n。<="" p="">
Day1
矩阵乘法应用。
《十个利用矩阵乘法解决的经典题目》from matrix67
矩阵乘法可以用来统计路径:
把原图建成邻接矩阵,另C=A*A,C(i,j)=sigma(A(i,k)*A(k,j)),C(i,j)就是从i到j且经过两条边的方案数。那么经过k条边就是A^(k-1)。
但是这道题有个限制:
不会沿着刚刚走来的路立刻走回。
上面的方法是会计算到这种情况的,因此需要改进一下:
把原来点的邻接矩阵变成边的邻接矩阵,如果A(i,j)=1,表示第i条边和第j条边相连,那么就不会立刻走刚刚走的边了(因为A(i,i)一定是0)
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <cstdlib> #define mod 45989 using namespace std; struct matrix { int f[125][125]; }a,b; int n,m,s,t; struct edge { int x,y; }e[500]; matrix Mult(matrix a,matrix b) { matrix ans; for (int i=0;i<2*m;i++) for (int j=0;j<2*m;j++) { ans.f[i][j]=0; for (int k=0;k<2*m;k++) ans.f[i][j]=(ans.f[i][j]+a.f[i][k]*b.f[k][j]%mod)%mod; } return ans; } matrix Pow(int n) { matrix ans; int f=0; while (n) { if (n&1) { if (f) ans=Mult(ans,b); else ans=b,f=1; } n>>=1; b=Mult(b,b); } return ans; } int main() { int l; scanf("%d%d%d%d%d",&n,&m,&l,&s,&t); for (int i=0;i<2*m;i+=2) { scanf("%d%d",&e[i].x,&e[i].y); e[i+1].x=e[i].y,e[i+1].y=e[i].x; } for (int i=0;i<2*m;i++) { for (int j=0;j<2*m;j++) if (j!=i&&j!=(i^1)&&e[j].x==e[i].y) b.f[i][j]=1; if (e[i].x==s) a.f[0][i]=1; } matrix ans=Mult(a,Pow(l-1)); int x=0; for (int i=0;i<2*m;i++) if (e[i].y==t) x=(x+ans.f[0][i])%mod; cout<<x<<endl; return 0; }