zoukankan      html  css  js  c++  java
  • 灾后重建(洛谷P1119,图论floyd)

                                                         P1119 灾后重建

    题目背景

    BBB地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。

    题目描述

    给出BBB地区的村庄数NNN,村庄编号从000到N−1N-1N1,和所有MMM条公路的长度,公路是双向的。并给出第iii个村庄重建完成的时间tit_iti,你可以认为是同时开始重建并在第tit_iti天重建完成,并且在当天即可通车。若tit_iti000则说明地震未对此地区造成损坏,一开始就可以通车。之后有QQQ个询问(x,y,t)(x, y, t)(x,y,t),对于每个询问你要回答在第ttt天,从村庄xxx到村庄y的最短路径长度为多少。如果无法找到从xxx村庄到yyy村庄的路径,经过若干个已重建完成的村庄,或者村庄xxx或村庄yyy在第t天仍未重建完成 ,则需要返回−1-11。

    输入格式

    第一行包含两个正整数N,MN,MN,M,表示了村庄的数目与公路的数量。

    第二行包含NNN个非负整数t0,t1,…,tN−1t_0, t_1,…, t_{N-1}t0,t1,,tN1,表示了每个村庄重建完成的时间,数据保证了t0≤t1≤…≤tN−1t_0 ≤ t_1 ≤ … ≤ t_{N-1}t0t1tN1

    接下来MMM行,每行333个非负整数i,j,wi, j, wi,j,w,www为不超过100001000010000的正整数,表示了有一条连接村庄iii与村庄jjj的道路,长度为www,保证i≠ji≠ji=j,且对于任意一对村庄只会存在一条道路。

    接下来一行也就是M+3M+3M+3行包含一个正整数QQQ,表示QQQ个询问。

    接下来QQQ行,每行333个非负整数x,y,tx, y, tx,y,t,询问在第ttt天,从村庄xxx到村庄yyy的最短路径长度为多少,数据保证了ttt是不下降的。

    输出格式

    QQQ行,对每一个询问(x,y,t)(x, y, t)(x,y,t)输出对应的答案,即在第ttt天,从村庄xxx到村庄yyy的最短路径长度为多少。如果在第t天无法找到从xxx村庄到yyy村庄的路径,经过若干个已重建完成的村庄,或者村庄x或村庄yyy在第ttt天仍未修复完成,则输出−1-11。

    输入输出样例

    输入 #1
    4 5
    1 2 3 4
    0 2 1
    2 3 1
    3 1 2
    2 1 4
    0 3 5
    4
    2 0 2
    0 1 2
    0 1 3
    0 1 4
    输出 #1
    -1
    -1
    5
    4

    说明/提示

    对于30%30\%30%的数据,有N≤50

    对于30%30\%30%的数据,有ti=0t_i= 0ti=0,其中有20%20\%20%的数据有ti=0N>50

    对于50%50\%50%的数据,有Q≤100

    对于100%100\%100%的数据,有N≤200M≤N×(N−1)/2,Q<=50000,所有输入数据涉及整数均不超过100000100000100000。

    思路:非常好的floyd练习题,因为这道题我加深了对floyd本质的认识;

    1 for(int k=1;k<=n;k++){
    2     for(int i=1;i<=n;i++){
    3         for(int j=1;j<=n;j++){
    4             f[i][j]=f[i][k]+f[k][j];
    5         }
    6     }
    7 }

    floyd本质:最开始只允许经过1号顶点进行中转,接下来只允许经过1和2号顶点进行中转……允许经过1~n号所有顶点进行中转,求任意两点之间的最短路程。用一句话概括就是:从i号顶点到j号顶点只经过前k号点的最短路程。

    这也是此题的关键思路。

    下面是代码(有详解)

     1 #include<cstdio>
     2 const int maxn=200+10,inf=0x3f3f3f3f;
     3 int a[maxn],w[maxn][maxn],f[maxn][maxn];
     4 int n;
     5 void Init(){
     6     for(int i=0;i<n;i++){
     7         for(int j=0;j<n;j++){
     8             f[i][j]=inf;
     9         }
    10     }
    11     for(int i=0;i<n;i++) f[i][i]=0;
    12 }
    13 void work(int k){
    14     for(int i=0;i<n;i++){
    15         for(int j=0;j<n;j++){
    16             if(f[i][j]>f[i][k]+f[k][j]) f[i][j]=f[i][k]+f[k][j];
    17         }
    18     }
    19 }
    20 int main(){
    21     int m;
    22     scanf("%d%d",&n,&m);
    23     for(int i=0;i<n;i++) scanf("%d",&a[i]);//读入每个村庄修建好时间(因为按顺序给出,所以不用先记录在排序)
    24     Init();//初始化(普通的floyd)
    25     for(int i=1;i<=m;i++){
    26         int x,y,z;
    27         scanf("%d%d%d",&x,&y,&z);
    28         f[x][y]=f[y][x]=z;//初始化(普通的floyd)
    29     }
    30     int q;
    31     scanf("%d",&q);
    32     int last=0;
    33     for(int i=1;i<=q;i++){
    34         int x,y,t;
    35         scanf("%d%d%d",&x,&y,&t);//读入每个询问
    36         if(a[x]>t||a[y]>t){
    37             printf("-1
    ");
    38             continue;
    39         }//如果x或y未修建好,直接输出-1
    40         int j;
    41         for(j=last;j<n;j++){
    42             if(a[j]>t) break;
    43             work(j);
    44         }//寻找在t之前修好的且没有用过他来松弛的村庄来松弛,结合之前的初始化,开始时给f数组附上了一些值,不用担心这会影响结果,因为x,y在t或t之前被修好的
    45         last=j;//所以j更新t以后的对答案无太大影响,且刚好他更新完了后边的,这就是floyd算法,所以之前的x或y是否修建好的判断一定要有,不然若j更新了,答案会错
    46         if(f[x][y]==inf) printf("-1
    ");
    47         else printf("%d
    ",f[x][y]);
    48     }
    49     return 0;
    50 }
    View Code
  • 相关阅读:
    几个新角色:数据科学家、数据分析师、数据(算法)工程师
    人类投资经理再也无法击败电脑的时代终将到来了...
    Action Results in Web API 2
    Multiple actions were found that match the request in Web Api
    Routing in ASP.NET Web API
    how to create an asp.net web api project in visual studio 2017
    网站漏洞扫描工具
    How does asp.net web api work?
    asp.net web api history and how does it work?
    What is the difference between a web API and a web service?
  • 原文地址:https://www.cnblogs.com/HZOIDJ123/p/13423054.html
Copyright © 2011-2022 走看看