zoukankan      html  css  js  c++  java
  • 【洛谷P1119题解】灾后重建——(floyd)

    这道题告诉我,背的掉板子并不能解决一切问题,理解思想才是关键,比如不看题解,我确实想不清楚这题是弗洛伊德求最短路

    (我不该自不量力的说我会弗洛伊德了我错了做人果然要谦虚)


     灾后重建

    题目背景

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

    题目描述

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

    输入格式

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

    第二行包含N个非负整数t0,t1,,tN1,表示了每个村庄重建完成的时间,数据保证了t0t1tN1

    接下来M行,每行3个非负整数i, j, w为不超过1000010000的正整数,表示了有一条连接村庄i与村庄j的道路,长度为w,保证i≠j,且对于任意一对村庄只会存在一条道路。

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

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

    输出格式

    QQ行,对每一个询问(x, y, t)(x,y,t)输出对应的答案,即在第tt天,从村庄xx到村庄yy的最短路径长度为多少。如果在第t天无法找到从xx村庄到yy村庄的路径,经过若干个已重建完成的村庄,或者村庄x或村庄yy在第tt天仍未修复完成,则输出-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%的数据,有N≤50N50;

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

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

    对于100\%100%的数据,有N≤200N200,M≤N imes (N-1)/2MN×(N1)/2,Q≤50000Q50000,所有输入数据涉及整数均不超过100000100000。

    看到那个 n<200 可能就可以用弗洛伊德了

    这题主要就是和用重建完成的村庄更新之前的最短路(就像弗洛伊德算法的思想,用 k 更新 i 到 j 的最短路),对于每一个询问时间就往后推,到询问时间为止,再判断是否连通然后输出。实际处理上还行,输入保证t由小到大递增非常省事

    更多对着代码想想,这题算法思想还行

    代码如下

    #include<cstdio>
    #include<iostream>
    using namespace std;
    int n,m,t[205],f[205][205];
    inline void update(int k)
    {
        for (int i=0; i<n; i++)
        for (int j=0; j<n; j++)
        {
            f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
            f[j][i]=f[i][j];
        }
    }//弗洛伊德,这道题的一、、、坑就是这个无向图在这里面也得存两次 
    int main()
    {
        cin>>n>>m;
        for (int i=0; i<n; i++)
        for (int j=0; j<n; j++)
        f[i][j]=1e9;    
        for (int i=0; i<n; i++)
        f[i][i]=0;
        for (int i=0; i<n; i++)
        cin>>t[i];
        for (int i=1; i<=m; i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            f[x][y]=z;
            f[y][x]=z;
        }//读入和初始化结束 
        int q;
        cin>>q;
        int now=0;
        for (int i=1; i<=q; i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            while (now<n&&t[now]<=z)
            {
                update(now);
                now++;
            }//到当前时间点所有最短路更新完毕 
            if (t[x]>z||t[y]>z) cout<<"-1"<<endl;
            else if (f[x][y]==1e9) cout<<"-1"<<endl;
            //判断两种无法走到的情况(放在一起判断会WA!!) 
            else cout<<f[x][y]<<endl;
        }
        return 0;
    }
    结束,就是这样短短49行(你码风比我好的话会更短 

    好的就是这些

    ありがとうございます

  • 相关阅读:
    面向对象编程技术的总结和理解(c++)
    对类的理解(c++)
    对指针和引用的理解(c++)
    3DES对称加密算法(ABAP 语言实现版)
    org.springframework.util.Base64Utils线程安全问题
    SAP传输请求自动发布
    ABAP WB01 BDC ”No batch input data for screen & &“ ”没有屏幕 & & 的批输入数据“
    SAP S/4 1610 IDES + HANA 2.0 安装
    ABAP语言实现 左移 <<、无符号右移 >>> 位移操作
    ABAP表抛FTP通用程序
  • 原文地址:https://www.cnblogs.com/Phantomhive/p/11693169.html
Copyright © 2011-2022 走看看