洛谷P1119灾后重建
做一个替我们首先要明确一下数据范围,n《=200,说明n^3的算法是可以过得,而且这个题很明显是一个图论题, 所以我们很容易想到这个题可以用folyd, 但是我在做这个题的时候因为没有深刻理解folyd的意义,因此导致调试了好几小时,
folyd 的思想是dp,我们可以用表示
和
之间可以通过编号为
的节点的最短路径。
初值为原图的邻接矩阵。
则可以从
转移来,表示
到
不经过
这个节点。
也可以从转移过来,表示经过
这个点。
意思即
然后你就会发现最外层一维空间可以省略,因为
只与
有关。
因此我们在dp循环的时候可以使用滚动数组,可以节约点空间。
这时候我们就可以看回原题了,我们可以先想比较暴力点的算法,就是直接采用floyd,不加任何优化,这样会很慢,因此我们可以寻找可以优化的方法,比如题目中的时间是递增的,因此我们每次状态转移的时候并不用每次都从第一个点找,而是可以接着上一次的询问。
这样题目就一目了然了。
坑点:他的编号都是从0开始的,且初始化数组的时候不能开太大,否则会爆
代码:
#include <iostream> #include <cstring> #include <algorithm> #include <cstdlib> #include <cstdio> #define M 550 using namespace std; int n, m, dis[M][M], t[M], now, ha, k; int main() { scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) { dis[i][j] = 214748364; } for(int i = 0; i < n; i++) scanf("%d", &t[i]); for(int i = 1; i <= m; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); dis[a][b] = c; dis[b][a] = c; } scanf("%d", &ha); for(int g = 1; g <= ha; g++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); for(k = now; k < n; k++) { if(t[k] > c) break; else for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); } now = k++; if(dis[a][b] != 214748364 && t[a] <= c && t[b] <= c) printf("%d\n", dis[a][b]); else printf("-1\n"); } }
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· Cursor预测程序员行业倒计时:CTO应做好50%裁员计划
· 当职场成战场:降职、阴谋与一场硬碰硬的抗争
· 用99元买的服务器搭一套CI/CD系统
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· Excel百万数据如何快速导入?