• 洛谷P1119 灾后重建 图论 脑洞题


    洛谷P1119 灾后重建

    图论   脑洞题   floyd   
    floyd中 k 的意义 通过前 k 个点 作为中间的节点 更新 i 到 j 的最短路 也就是 只经过前 k 个点 的最短路


    帮助理解Floyd算法的好题!初学Floyd算法时,相信很多人和我一样,只是把几行代码背下来,
    并没有了解Floyd算法到底是什么原理。以下介绍Floyd算法的原理:

    Floyd算法的本质是动态规划,其转移方程为:f(k,i,j) = min( f(k-1,i,j), f(k-1,i,k)+f(k-1,k,j) )。

    f(k,i,j)表示路径除开起点i与终点j,只经过前k个点中的某些点,从i到j的最小值。计算这个值只需要考虑两种情况:
    最短路经过k,和最短路不经过k(那么就经过前k-1个点中的某些点)。由于k要从k-1转移而来,自然k为最外层的循环。
    而经过状态压缩(类似于背包问题)后,就变成了我们熟悉的f(i,j) = min( f(i,j), f(i,k)+f(k,j) )了。

    本题同理,只是k表示的是最先修好的前k个村庄。不过由于出题人非常良心地帮我们把修理时间和询问时间都排序了,
    所以就没什么关系了- -用Floyd枚举k时,枚举到下一个询问的时间点就停止。回答询问之后,再继续枚举。

     1 #include <cstdio>
     2 #include <cmath>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <string>
     6 #include <iostream>
     7 #include <iomanip>
     8 using namespace std ; 
     9 
    10 const int maxn = 211,maxq = 50011,inf = 1e9 ; 
    11 int n,m,Q,now ; 
    12 int e[maxn][maxn],t[maxn] ; 
    13 int tq[maxq],qs[maxq],qt[maxq] ; 
    14 
    15 inline int read() 
    16 {
    17     char ch = getchar() ; 
    18     int x = 0 , f = 1 ; 
    19     while(ch<'0'||ch>'9') { if( ch=='-' ) f = -1 ; ch = getchar() ; } 
    20     while(ch>='0'&&ch<='9') { x = x*10 + ch - 48 ; ch = getchar() ; } 
    21     return x * f ; 
    22 }
    23 
    24 inline int print(int now) 
    25 {
    26     if( t[ qs[now] ] > tq[ now ] || t[ qt[now] ] > tq[ now ] ) 
    27         return -1 ; 
    28     if( e[qs[now]][qt[now]]==inf ) 
    29         return -1 ; 
    30     return e[qs[now]][qt[now]] ;  
    31 }
    32 
    33 int main() 
    34 {
    35     n = read() ; m = read() ; 
    36     for(int i=0;i<n;i++) t[ i ] = read() ; 
    37     for(int i=0;i<n;i++) 
    38         for(int j=0;j<n;j++) e[ i ][ j ] = inf ; 
    39         
    40     
    41     int x,y,v ; 
    42     for(int i=1;i<=m;i++) 
    43     {
    44         x = read() ; y = read() ; v = read() ; 
    45         e[ x ][ y ] = v ; e[ y ][ x ] = v ; 
    46     }
    47     
    48     Q = read() ;  
    49     for(int i=1;i<=Q;i++) 
    50     {
    51         qs[ i ] = read() ; qt[ i ] = read() ; tq[ i ] = read() ;   
    52     }
    53     
    54     now = 1 ; 
    55     for(int k=0;k<n;k++) 
    56     {
    57         while( now <= Q && tq[now] < t[ k ] )    // 这样相当于做询问 Q 是 就已经将 在他之前的 边考虑到
    58                                                 //询问的时间小于当前时间则输出 
    59         {
    60             printf("%d
    ",print( now ) ) ; 
    61             now++ ; 
    62         }
    63         for(int i=0;i<n;i++) 
    64             for(int j=0;j<n;j++) 
    65                 e[ i ][ j ] = min(e[ i ][ j ],e[ i ][ k ] + e[ k ][ j ]) ; 
    66     }
    67     
    68     while( now<=Q ) 
    69     {
    70         printf("%d
    ",print(now)) ; 
    71         now++ ; 
    72     }
    73      
    74     return 0 ; 
    75 }
  • 相关阅读:
    JavaScript最佳实践
    Ionic2学习笔记(3):Pipe
    广商14级软件工程分数:第十一回合
    Ionic2学习笔记(2):自定义Component
    Ionic2学习笔记(1):新建一个页面
    Ionic2学习笔记(0):HelloWorld
    采用Kettle分页处理大数据量抽取任务
    广商14级软件工程分数:第十回合
    广商14级软件工程分数:第九回合
    广商14级软件工程-项目介绍视频汇总
  • 原文地址:https://www.cnblogs.com/third2333/p/7097440.html
Copyright © 2020-2023  润新知