题目大意:有n个村庄和一些连通两个村庄的双向道路。每个村庄在一个特定的时间修复。没有修复的村庄不能经过。现在有一系列询问,问两个村庄在t时刻的最短路(如果无法到达或两个村庄本身未修复,输出-1)。

解题思路:村庄数量少,可以考虑floyd。

但询问与时间有关,不同时间内最短路是不同的,那么对每个询问都跑一遍最短路?$O(qn^3)$的时间复杂度一定会超时。

不过我们可以发现,如果t1~t2时间段内,没有任何修改,就不必每次跑一遍最短路。

而且,floyd第一重循环是枚举中间点的,那我们按照修复时间从小到大枚举中间点,然后进行后两重循环,就能保证此次循环后的状态是修复了这个村庄后,而后面的村庄还未修复时的状态。

然后在这中间处理询问即可。

这样做相当于只跑了一遍floyd就处理完了询问,所以总时间复杂度$O(q+n^3)$,即可通过此题。

C++ Code:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;
int n,m,dis[202][202],tm[202];
struct sj{
int t,num;
bool operator<(const sj& rhs)const{return t<rhs.t;}
}p[202];
inline int readint(){
char c=getchar();
for(;!isdigit(c);c=getchar());
int d=0;
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
int main(){
n=readint(),m=readint();
for(int i=0;i<n;++i)
p[i]=(sj){tm[i]=readint(),i};
sort(p,p+n);
memset(dis,0x3f,sizeof dis);
while(m--){
int x=readint(),y=readint(),z=readint();
dis[x][y]=dis[y][x]=z;
}
m=readint();
int now=1,x=readint(),y=readint(),t=readint();
p[n].t=0x3f3f3f3f;
for(int f=0;;++f){
int k=p[f].num;
while(p[f].t>t){
if(tm[x]>t||tm[y]>t||dis[x][y]==0x3f3f3f3f)puts("-1");else
printf("%d\n",dis[x][y]);
if(++now>m)return 0;
x=readint(),y=readint(),t=readint();
}
if(f==n)return 0;
for(int i=0;i<n;++i)
if(i!=k)
for(int j=0;j<n;++j)
if(i!=j&&j!=k&&dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
}
return 0;
}

由于洛谷支持Java了,我又写了个Java的代码,比较丑陋,而且时间也极慢。但还是能过去的。

Java Code:

import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args)throws IOException{
StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
in.nextToken();
int n=(int)in.nval,m,tm[]=new int[202],tm2[]=new int[202],dis[][]=new int[202][202],nb[]=new int[202];
in.nextToken();
m=(int)in.nval;
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)dis[i][j]=0x3f3f3f3f;
for(int i=0;i<n;++i){
in.nextToken();
tm[i]=tm2[i]=(int)in.nval;
nb[i]=i;
}
for(int i=0;i<n;++i)
for(int j=i+1;j+1<n;++j)
if(tm[i]>tm[j]){
int t=tm[i];
tm[i]=tm[j];
tm[j]=t;
t=nb[i];
nb[i]=nb[j];
nb[j]=t;
}
while(m!=0){
--m;
int x,y,z;
in.nextToken();
x=(int)in.nval;
in.nextToken();
y=(int)in.nval;
in.nextToken();
z=(int)in.nval;
dis[x][y]=dis[y][x]=z;
}
in.nextToken();
m=(int)in.nval;
int x,y,t,now=1;
in.nextToken();x=(int)in.nval;
in.nextToken();y=(int)in.nval;
in.nextToken();t=(int)in.nval;
tm[n]=0x3f3f3f3f;
for(int p=0;;++p){
int k=nb[p];
while(tm[p]>t){
if(tm2[x]>t||tm2[y]>t||dis[x][y]==0x3f3f3f3f)
out.println(-1);else
out.println(dis[x][y]);
++now;
if(now>m){
out.close();
return;
}
in.nextToken();x=(int)in.nval;
in.nextToken();y=(int)in.nval;
in.nextToken();t=(int)in.nval;
}
if(p==n)break;
for(int i=0;i<n;++i)
if(i!=k)
for(int j=0;j<n;++j)
if(i!=j&&j!=k&&dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
}
out.close();
}
}

[洛谷P1119][codevs1817]灾后重建的更多相关文章

  1. 【洛谷P1119】灾后重建

    题目大意:给定一个 N 个顶点,M 条边的无向图,每个顶点有一个时间戳,且时间戳大小按照顶点下标大小依次递增,在给定时间 t 时,时间戳严格大于 t 的顶点不能被访问,现在有 Q 次询问,每次询问在给 ...

  2. 洛谷 P 1119 灾后重建

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

  3. 洛谷——P1119 灾后重建

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

  4. 洛谷 P1119 灾后重建 最短路+Floyd算法

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例 输出样例 说明 思路 AC代码 总结 题面 题目链接 P1119 灾后重建 题目描述 B地区在地震过后,所有村 ...

  5. AC日记——灾后重建 洛谷 P1119

    灾后重建 思路: 看到n<=200,思考弗洛伊德算法: 如何floyed呢? floyed是一种动态规划求最短路的算法: 它通过枚举中间点来更新两点之间最短路: 回到这个题本身: 所有点的重建完 ...

  6. 【洛谷P1119题解】灾后重建——(floyd)

    这道题告诉我,背的掉板子并不能解决一切问题,理解思想才是关键,比如不看题解,我确实想不清楚这题是弗洛伊德求最短路 (我不该自不量力的说我会弗洛伊德了我错了做人果然要谦虚) 灾后重建 题目背景 B地区在 ...

  7. [Luogu P1119] 灾后重建 (floyd)

    题面 传送门:https://www.luogu.org/problemnew/show/P1119 Solution 这题的思想很巧妙. 首先,我们可以考虑一下最暴力的做法,对每个时刻的所有点都求一 ...

  8. CODEVS 1817 灾后重建 Label:Floyd || 最短瓶颈路

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

  9. java实现第六届蓝桥杯灾后重建

    灾后重建 题目描述 Pear市一共有N(<=50000)个居民点,居民点之间有M(<=200000)条双向道路相连.这些居民点两两之间都可以通过双向道路到达.这种情况一直持续到最近,一次严 ...

随机推荐

  1. BZOJ 3166 set+可持久化trie树(OR 莫队)

    思路: 1.找次大值 我们不妨设当前点是次大的 那这段区间为 左边第二个比它大的点的坐标+1 和右边第二个比它大的点的坐标-1 2.用可持久化trie树找异或最大值 也可以用莫队 //By Siriu ...

  2. vim编辑器常用语法

    1)yy (功能描述:复制光标当前一行) y数字y (功能描述:复制一段(从第几行到第几行))2)p (功能描述:箭头移动到目的行粘贴)3)u (功能描述:撤销上一步)4)dd (功能描述:删除光标当 ...

  3. 【原创】VSFTP: Login failure: 530 Login incorrect的解决办法

    1.修改/etc/vsftpd/ftpusers和/etc/vsftpd/user_list中关于root的行,注释掉即可: 2.关闭SELinux:如果不想关闭的话,可以打开home项的布林值:se ...

  4. lua中调用C++函数

    lua中调用C++函数 我们产品中提供了很多lua-C API给用户在lua中调用,之前一直没用深究其实现原理,只是根据已有的代码在编码.显然这不是一个好的习惯,没用达到知其所以然的目的. 一.基本原 ...

  5. AJAX和JSON笔记

    ### 1. 响应正文  传统的处理请求时,响应的方式有转发或重定向,无论是哪种,最终都会直接呈现某个页面给客户端,这样做的缺点在于:  1. 用户体验可能不好,例如:用户注册时,提交的用户名被占用, ...

  6. NodeJS学习笔记 (3)域名解析-dns(ok)

    域名解析:dns.lookup() 比如我们要查询域名 www.qq.com 对应的ip,可以通过 dns.lookup() . var dns = require('dns'); dns.looku ...

  7. [POJ2823][洛谷P1886]滑动窗口 Sliding Window

    题目大意:有一列数,和一个窗口,一次能框连续的s个数,初始时窗口在左端,不断往右移动,移到最右端为止,求每次被框住的s个数中的最小数和最大数. 解题思路:这道题是一道区间查询问题,可以用线段树做.每个 ...

  8. spring中IOC的简单使用

    spring的ioc主要就是依赖注入,有基于构造器的依赖注入还有通过设值注入,这里我只简单的实现设值注入的方法,通过spring的依赖管理,我们可以很方便的了解各层之间的依赖关系,降低了各层之间的耦合 ...

  9. Camera Calibration 相机标定:原理简介(五)

    5 基于2D标定物的标定方法 基于2D标定物的标定方法,原理与基于3D标定物相同,只是通过相机对一个平面进行成像,就可得到相机的标定参数,由于标定物为平面,本身所具有的约束条机,相对后者标定更为简单. ...

  10. [Typescript] Build Method decorators in Typescript

    To using decorate, we can modifiy tsconfig.json: { "compilerOptions": { ... "experime ...