BZOJ 2165: 大楼 倍增Floyd
卡了一上午常数,本地13s,可是bzoj 就是过不去~
#include <bits/stdc++.h> #define N 102 #define M 55 #define ll long long #define inf -1 #define setIO(s) freopen(s".in","r",stdin) , freopen("de.out","w",stdout) using namespace std; char *p1,*p2,buf[100000]; #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++) int rdint() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;} ll rdll() {ll x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;} int n; ll m; ll f[N][N],dis[N][N][70],tmp[N],g[N]; void solve() { int i,j,k; n=rdint(); m=rdll(); for(i=0;i<=n;++i) for(j=0;j<=n;++j) for(k=0;k<70;++k) dis[i][j][k]=-1; for(i=1;i<=n;++i) { for(k=0;k<=M;++k) dis[i][i][k]=0; } for(i=1;i<=n;++i) { for(j=1;j<=n;++j) { ll p=rdll(); if(p) { dis[i][j][0]=max(dis[i][j][0], p); } } } for(int l=1;;++l) { for(k=1;k<=n;++k) { for(i=1;i<=n;++i) { for(j=1;j<=n;++j) { if(dis[i][k][l-1]!=-1 && dis[k][j][l-1]!=-1) { dis[i][j][l]=max(dis[i][j][l], dis[i][k][l-1]+dis[k][j][l-1]); } } } } ll re=0; for(i=1;i<=n;++i) re=max(re, dis[1][i][l]); if(re>=m) { i=l; break; } } int flag=0; ll ans=0; for(int l=i;l>=0;--l) { if(!flag) { flag=1; for(i=1;i<=n;++i) { if(dis[1][i][l]>=m) { flag=0; } } if(flag==0) continue; else { // for(i=1;i<=n;++i) for(j=1;j<=n;++j) tmp[j]=dis[1][j][l]; ans+=(1ll<<l); } } else { for(i=0;i<=n;++i) g[i]=-1; for(k=1;k<=n;++k) { for(j=1;j<=n;++j) { if(dis[k][j][l]!=inf && tmp[k]!=inf) { g[j]=max(g[j], tmp[k]+dis[k][j][l]); } } } int cc=0; for(i=1;i<=n;++i) if(g[i]>=m) cc=1; if(!cc) { for(j=1;j<=n;++j) tmp[j]=g[j]; ans+=(1ll<<l); } } } printf("%lld\n",ans+1); } int main() { // setIO("input"); int T; scanf("%d",&T); while(T--) { solve(); } return 0; }