zoukankan      html  css  js  c++  java
  • LuoguP1119 灾后重建

    Description

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

    Analysis

    这道题考察floyd的本质,若用朴素的floyd,循环Q次,每次都要跑O(N3)的Floyd,则复杂度为O(N3Q)。这里其实不需要枚举最外层循环k,如果在某个时间t,找到一个_T[k] <= t,则将其作为中间点更新最短距离。这样每次询问都找到时间小于t的k,k不断自加,最终时间复杂度O(N^3 + Q)。(我也不知道为什么T[]不排序也可以AC)

    Code

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    #include <vector>
    #define N 210
    using namespace std;
    int G[N][N],T[N],_T[N],n,m,q,x,y,t,k;
    void floyd(){
            // P.S. 我就是忘了 k < n只得了40分
            //因为T初始为0
            //当然也可以初始化T[n] = inf就不用判断了
    	while(T[k] <= t && k < n){
    		for(int i = 0;i < n;++i){
    			for(int j = 0;j < n;++j){
    				G[i][j] = min(G[i][j],G[i][k] + G[k][j]);
    			}
    		}
    	++k;
    	}
    }
    void solve(){
    	floyd();
    	if(T[x] > t || T[y] > t || G[x][y] == 0x3f3f3f3f) printf("-1
    ");
    	else printf("%d
    ",G[x][y]);
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	memset(G,0x3f,sizeof(G));
    	for(int i = 0;i < n;++i){
    		G[i][i] = 0;
    		scanf("%d",&T[i]);
    	}
    	for(int i = 1;i <= m;++i){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		G[u][v] = G[v][u] = w;
    	}
    	scanf("%d",&q);
    	for(int i = 1;i <= q;++i){
    		scanf("%d%d%d",&x,&y,&t);
    		solve();
    	}
    	return 0;
    }
    
    岂能尽如人意,但求无愧我心
  • 相关阅读:
    JAVA基础知识|HTTP协议-两个特性
    JAVA基础知识|TCP/IP协议
    Spring Cloud|高可用的Eureka集群服务
    Hadoop环境搭建|第四篇:hive环境搭建
    C#中Func与Action的理解
    C# lambda表达式
    WPF ControlTemplate
    sublime text3插件安装及使用
    Dev Express之ImageComboBoxEdit,RepositoryItemImageComboBox使用方式
    SQL查询结果增加序列号
  • 原文地址:https://www.cnblogs.com/Zforw/p/10541853.html
Copyright © 2011-2022 走看看