老稿新发,之前的有问题。
【题目】
https://www.luogu.com.cn/problem/P1613
【审题】
1.每秒钟可以跑2^k千米(k是任意自然数);
2.总跑路长度不能超过maxlongint千米;
3.有向图。
【分析】
首先,这是一个有向图单源最短路问题。但是这里的路程不是边权和,而是走过的时间和。我们尽力使时间最小,如果两点之间可以用一秒走到,我们就绝对不用两秒走到。
题中已经说明,每秒可跑2^k千米(k是任意自然数),则只要两点间存在一条长度为2的倍数的路径,就可以在1秒内从其中一点走到另一点。
由此,我们可以对该图进行预处理。
设f[i][j][k]为从i点到j点间是否存在一条长度为2^k的路径,即i到j是否只需要1秒钟。
我们枚举i,j,k以及中转点h。若i到h间存在一条长度为2^(k-1)的路径,i到h间存在一条长度为2^(k-1)的路径,则i到j存在一条长度为2^k的路径,i可以用1秒到j,路径长就更新为1.
n<=50,则这道题可以轻轻松松用Floyd水过。
【代码实现】
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 int dis[55][55]; 5 bool f[55][55][65]; 6 int n,m; 7 signed main() { 8 memset(dis,10,sizeof(dis)); 9 memset(f,0,sizeof(f)); 10 scanf("%lld %lld",&n,&m); 11 for(int i=1; i<=m; i++) { 12 int u,v; 13 scanf("%lld %lld",&u,&v); 14 f[u][v][0]=1; 15 dis[u][v]=1; 16 } 17 18 for(int k=1; k<=64; k++) { 19 for(int i=1; i<=n; i++) { 20 for(int h=1; h<=n; h++) { 21 for(int j=1; j<=n; j++) { 22 if(f[i][h][k-1]&&f[h][j][k-1]) { 23 f[i][j][k]=1; 24 dis[i][j]=1;//最关键的一步 25 } 26 } 27 } 28 } 29 } 30 31 //floyd 32 for(int i = 1 ; i <= n ; i ++) dis[i][i] = 0; 33 for(int k=1; k<=n; k++) { 34 for(int i=1; i<=n; i++) { 35 for(int j=1; j<=n; j++) { 36 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); 37 } 38 } 39 } 40 printf("%lld",dis[1][n]); 41 return 0; 42 43 } 44 /* 45 4 4 46 1 1 47 1 2 48 2 3 49 3 4 50 */ 51 /* 52 7 8 53 1 6 54 5 1 55 6 4 56 4 5 57 5 2 58 3 7 59 7 5 60 2 3 61 62 */