本来是求点a到点b的路径
由于是完全图且K固定,就可以当成是每个原图点往k个中转点连了in[i][kj]条边,每个中转点往每个原图点连了out[kj][i]条边
于是我们就可以把中转点和原图点反一下
求两个原图点的路径就变成了求两个中转点的路径
用矩乘快速幂就可以了
如图ki,kj为中转点
如图如果从1到4沿着黑色边走的话,就可以当做是 ki到kj的方案数 x 1到ki的方案数 x kj到4的方案数
复杂度:O(k^3)
矩乘:O(k^3*log2(d-1))很优秀啊……
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<string> 7 #include<cmath> 8 #include<ctime> 9 #include<queue> 10 #include<stack> 11 #include<map> 12 #include<set> 13 #define rre(i,r,l) for(int i=(r);i>=(l);i--) 14 #define re(i,l,r) for(int i=(l);i<=(r);i++) 15 #define Clear(a,b) memset(a,b,sizeof(a)) 16 #define inout(x) printf("%d",(x)) 17 #define douin(x) scanf("%lf",&x) 18 #define strin(x) scanf("%s",(x)) 19 #define LLin(x) scanf("%lld",&x) 20 #define op operator 21 #define CSC main 22 typedef unsigned long long ULL; 23 typedef const int cint; 24 typedef long long LL; 25 using namespace std; 26 void inin(int &ret) 27 { 28 ret=0;int f=0;char ch=getchar(); 29 while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} 30 while(ch>='0'&&ch<='9')ret*=10,ret+=ch-'0',ch=getchar(); 31 ret=f?-ret:ret; 32 } 33 int out[2010][22],in[22][2010],ans; 34 cint mod=1e9+7; 35 int n,m,l[22]; 36 struct Mat 37 { 38 LL a[25][25]; 39 void in(int x) 40 { 41 re(i,1,m)re(j,1,m)a[i][j]=(i==j)*x; 42 } 43 LL* op [] (int x){return x[a];} 44 Mat op + (Mat rhs) 45 { 46 Mat ret;ret.in(0); 47 re(i,1,m)re(j,1,m)ret[i][j]=(a[i][j]+rhs[i][j]%mod)%mod; 48 return ret; 49 } 50 Mat op * (Mat rhs) 51 { 52 Mat ret;ret.in(0); 53 re(i,1,m)re(j,1,m)re(k,1,m) 54 ret[i][k]=(ret[i][k]+1LL*a[i][j]*rhs[j][k])%mod; 55 return ret; 56 } 57 }ii,hh; 58 Mat ret,shu; 59 void solve(int x) 60 { 61 if(x<0)return ret=hh,void(); 62 Mat a=shu,b=a,v=ii,s=ii; 63 ret.in(0); 64 while(x) 65 { 66 if(x&1)s=s+(b*v),v=v*a; 67 x>>=1; 68 Mat k=a+ii; 69 b=b*k; 70 a=a*a; 71 } 72 ret=s; 73 } 74 int CSC() 75 { 76 inin(n),inin(m); 77 ii.in(1); 78 re(i,1,n) 79 { 80 re(j,1,m)inin(out[i][j]); 81 re(j,1,m)inin(in[j][i]); 82 } 83 shu.in(0);hh.in(0); 84 re(i,1,m)re(j,1,n)re(k,1,m) 85 shu[i][k]=(shu[i][k]+1LL*in[i][j]*out[j][k])%mod; 86 int q; 87 inin(q); 88 while(q--) 89 { 90 int a,b,d; 91 inin(a),inin(b),inin(d); 92 solve(d-1); 93 re(i,1,m)l[i]=0; 94 re(i,1,m)re(j,1,m)l[j]=(l[j]+1LL*out[a][i]*ret[i][j]%mod)%mod; 95 ans=0; 96 re(i,1,m)ans=(ans+1LL*l[i]*in[i][b])%mod; 97 printf("%d ",ans+(a==b)); 98 } 99 return 0; 100 }