跑路是一道简单题.
倍增和最短路的结合.
各大OJ上都有这道题,比如说:https://www.luogu.org/problemnew/show/P1613.
这道题仔细一分析,发现应该得先预处理再跑floyd.
我们得先预处理出一个bool数组dis[x][y][k],表示点x到点y之间的路是否有一条的权值为2^k.
那么大概就按照动态规划的思想,枚举一个中点u,dis[x][y][k]=dis[x][y][k]||dis[x][u][k-1]&&dis[u][y][k-1].
然后对一个存最短路的d数组初始化一波.
代码实现就这样:
inline void start(){ rep(k,1,31) rep(i,1,n) rep(j,1,n) rep(p,1,n) dis[i][j][k]=dis[i][j][k]||dis[i][p][k-1]&&dis[p][j][k-1]; memset(d,10,sizeof(d)); rep(k,0,31) rep(i,1,n) rep(j,1,n) if (dis[i][j][k]) d[i][j]=1; }
然后再跑一边floyd:
inline void floyd(){ rep(k,1,n) rep(i,1,n) rep(j,1,n) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); }
最后输出就好了.
AC代码如下:
扫描二维码关注公众号,回复:
391129 查看本文章
#include<bits/stdc++.h> using namespace std; #define rep(i,j,k) for (int i=j;i<=k;i++) int n,m; bool dis[51][51][32]={0}; int d[51][51]={0}; inline void into(){ scanf("%d%d",&n,&m); int x,y; rep(i,1,m){ scanf("%d%d",&x,&y); dis[x][y][0]=1; } } inline void start(){ rep(k,1,31) rep(i,1,n) rep(j,1,n) rep(p,1,n) dis[i][j][k]=dis[i][j][k]||dis[i][p][k-1]&&dis[p][j][k-1]; memset(d,10,sizeof(d)); rep(k,0,31) rep(i,1,n) rep(j,1,n) if (dis[i][j][k]) d[i][j]=1; } inline void floyd(){ rep(k,1,n) rep(i,1,n) rep(j,1,n) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); } inline void work(){ start(); floyd(); } inline void outo(){ printf("%d\n",d[1][n]); } int main(){ into(); work(); outo(); return 0; }
好了,手残地把i写成了1...
好吧.
OK就这样.