题目分析:
重新定义矩阵运算,$*$等价于$+$,$+$等价于$max$。
然后倍增一下,再二分一下。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int n;long long m; 5 struct mat{long long arr[102][102];}G,mmp; 6 mat hh[70]; 7 8 mat operator*(mat alpha,mat beta){ 9 int flag = 0; 10 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(alpha.arr[i][j]!=0)flag=1; 11 if(flag == 0) return beta; 12 memset(mmp.arr,0,sizeof(mmp.arr)); 13 for(int k=1;k<=n;k++){ 14 for(int i=1;i<=n;i++){ 15 for(int j=1;j<=n;j++){ 16 if(alpha.arr[i][k] == 0 || beta.arr[k][j] == 0) continue; 17 mmp.arr[i][j]= 18 max(mmp.arr[i][j],alpha.arr[i][k]+beta.arr[k][j]); 19 } 20 } 21 } 22 return mmp; 23 } 24 25 mat res; 26 long long fstpow(long long pw){ 27 hh[0] = G;pw *= 2; 28 int bit = 0; 29 while((1ll<<bit) <= pw){ 30 hh[bit+1] = hh[bit]*hh[bit];bit++; 31 int flag = 0; 32 for(int i=1;i<=n;i++) if(hh[bit].arr[1][i] >= m) flag = 1; 33 if(flag) break; 34 } 35 return bit; 36 } 37 38 void read(){ 39 scanf("%d%lld",&n,&m); 40 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lld",&G.arr[i][j]); 41 } 42 43 void work(){ 44 int z = fstpow(m); 45 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) res.arr[i][j] = 0; 46 long long ans = (1ll<<z); 47 long long now = 0; 48 while((--z) >= 0){ 49 mat maye = res*hh[z];int flag = 0; 50 for(int i=1;i<=n;i++) if(maye.arr[1][i] >= m){flag = 1;break;} 51 if(flag) ans = now+(1ll<<z); 52 else now += (1ll<<z),res = maye; 53 } 54 printf("%lld ",ans); 55 } 56 57 int main(){ 58 int Tmp; scanf("%d",&Tmp); 59 while(Tmp--){ 60 read(); 61 work(); 62 } 63 return 0; 64 }