给出一个有向图,判断 从 1 到 n 长度 为 k 的路径有几条
思路 邻接矩阵A^k 次幂,k=1 即 从 顶点 vi 到 vj 长度为 1的路径 有 A[i][j]条。。。
因为 k 很大,如果 直接暴力算 会超时,可采用 二分快速幂求解
假设 A^13
(13)10==(1101)2
那么 A^13==A^8*A^4*A^1
碰到 为 该位为 1 的 就将 A*(A的对应权重次幂),为 0 就 将权重 ^2
#include<iostream> #include<cstdio> using namespace std; typedef int LL; const int maxn=102; LL N,M,K,mod=10000; struct Mat{ LL mt[maxn][maxn]; }; Mat res,tmp,A; Mat MatMul(Mat a,Mat b){ Mat c; for(int i=0;i<N;i++){ for(int j=0;j<N;j++){ c.mt[i][j]=0; for(int k=0;k<N;k++){ c.mt[i][j]+=(a.mt[i][k]*b.mt[k][j])%mod; c.mt[i][j]%=mod; } } } return c; } Mat MatFun(Mat a,LL k){ tmp=a; a=res; while(k){ if(k&1)a=MatMul(a,tmp); tmp=MatMul(tmp,tmp); k>>=1; } return a; } void getRes(){ for(int i=0;i<N;i++)res.mt[i][i]=1; } int main(){ while(scanf("%d%d%d",&N,&M,&K)==3){ memset(A.mt,0,sizeof(A.mt)); memset(res.mt,0,sizeof(res.mt)); int x,y; while(M--){ scanf("%d%d",&x,&y); A.mt[x-1][y-1]=1; } getRes(); A=MatFun(A,K); printf("%d\n",A.mt[0][N-1]); //for(int i=0;i<N;i++){ // for(int j=0;j<N;j++)printf("%d",A.mt[i][j]); // puts(""); //} } return 0; }