洛谷 P1613 跑路

老稿新发,之前的有问题。


 

【题目】

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 */

 

posted @ 2021-11-16 19:29  TheZealous  阅读(68)  评论(0编辑  收藏  举报