HDU6331 Problem M. Walking Plan【Floyd + 矩阵 + 分块】
HDU6331 Problem M. Walking Plan
题意:
给出一张有\(N\)个点的有向图,有\(q\)次询问,每次询问从\(s\)到\(t\)且最少走\(k\)条边的最短路径是多少
\(N\le 50, q\le 10^5, k\le 10^4\)
题解:
如果暴力预处理的话复杂度是\(kN^3\)也就是\(1.25\times 10^9\),空间上肯定开不起
第二个想法就是对邻接矩阵进行矩阵快速幂,对于每次询问都要跑一次,复杂度是\(qN^3\log k\)复杂度更高了
考虑分摊复杂度,\(k\)最多是\(10^4\),那么可以每\(\lfloor\sqrt{k}\rfloor\)的长度跑一次最短路,跑\(\lceil\frac{k}{\lfloor\sqrt{k}\rfloor}\rceil\)次,最后计算的时候询问\(k\)可以把\(k\)拆成\(l\times \sqrt{k} + r\),然后用两个对应的最短路矩阵再找一次最短路即可,要注意的是,最短路不一定是单调的,也就是说可能走更多的边可以得到更短的路径,但是多走的边不会超过\(N\),因为两点之间的最短路长度是不会超过顶点数的,所以预处理时需要计算的是\(u\)到\(v\)走了至少\(k\)步的最短路,最后的复杂度是\(\sqrt{k}N^3+qN\)大概是\(2\times 10^7\)
view code
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 55;
const int INF = 0x3f3f3f3f;
int n, m;
struct Matrix{
int A[MAXN][MAXN];
Matrix(){ for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) A[i][j] = INF; }
void clear(){ for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) A[i][j] = INF; }
Matrix operator * (const Matrix &rhs) const{
Matrix ret;
for(int k = 1; k <= n; k++)
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
ret.A[i][j] = min(ret.A[i][j],A[i][k] + rhs.A[k][j]);
return ret;
}
};
Matrix dis1[155], dis100[111];
void solve(){
scanf("%d %d",&n,&m);
dis1[1].clear();
for(int i = 1; i <= m; i++){
int u, v, w;
scanf("%d %d %d",&u,&v,&w);
dis1[1].A[u][v] = min(dis1[1].A[u][v],w);
}
for(int i = 2; i <= 150; i++) dis1[i] = dis1[i-1] * dis1[1];
dis100[1] = dis1[100];
for(int i = 2; i <= 100; i++) dis100[i] = dis100[i-1] * dis100[1];
for(int i = 149; i >= 1; i--)
for(int u = 1; u <= n; u++)
for(int v = 1; v <= n; v++)
dis1[i].A[u][v] = min(dis1[i].A[u][v],dis1[i+1].A[u][v]);
int q;
scanf("%d",&q);
while(q--){
int s, t ,k;
scanf("%d %d %d",&s,&t,&k);
int ret = INF;
if(k<=100) ret = dis1[k].A[s][t];
else{
int l = (k-1) / 100, r = k - l * 100;
for(int i = 1; i <= n; i++) ret = min(ret,dis100[l].A[s][i] + dis1[r].A[i][t]);
}
printf("%d\n",ret==INF?-1:ret);
}
}
int main(){
int tt;
for(scanf("%d",&tt); tt; tt--) solve();
return 0;
}
HDU6331 Problem M. Walking Plan【Floyd + 矩阵 + 分块】的更多相关文章
- hdu6331 Problem M. Walking Plan
传送门 题目大意 给你一个n点m条边的有向图,q次询问,给定s,t,k,求由s到t至少经过k条边的最短路. 分析 我们设dp[i][j][k]为从i到j至少经过k条边的最短路,sp[i][j]意为从i ...
- 2018HDU多校训练-3-Problem M. Walking Plan
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6331 Walking Plan Problem Description There are n inte ...
- HDU6331Problem M. Walking Plan
传送门 分块floyd $f[i][j][k]$表示从i走k步到j的最短路 $g[i][j][k]$表示从i走k*100步到j的最短路 $h[i][j][k]$表示从i至少走k步到j的最短路 询问从x ...
- 2018 杭电多校3 - M.Walking Plan
题目链接 Problem Description There are $$$n$$$ intersections in Bytetown, connected with $$$m$$$ one way ...
- poj 3613 经过k条边最短路 floyd+矩阵快速幂
http://poj.org/problem?id=3613 s->t上经过k条边的最短路 先把1000范围的点离散化到200中,然后使用最短路可以使用floyd,由于求的是经过k条路的最短路, ...
- 【floyd+矩阵乘法】POJ 3613 Cow Relays
Description For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a rel ...
- 【做题】HDU6331 Walking Plan——矩阵&分块
题意:给出一个有\(n\)个结点的有向图,边有边权.有\(q\)组询问,每次给出\(s,t,k\),问从\(s\)到\(t\)至少经过\(k\)条边的最短路. \(n \leq 50, \, q \l ...
- 2018多校第三场 hdu6331 M :Walking Plan
题目链接 hdu6331 自我吐槽,这场多校大失败,开局签到因输入输出格式写错,wa了3发.队友C题wa了1个小时,还硬说自己写的没错,结果我随便造了个小数据,他都没跑对.然后跑对了后又进入了无限的卡 ...
- hdu6331 Walking Plan
题意: sol: 考虑floyed 直接暴力做的话复杂度是kn^3会炸. 考虑一个比较神仙的分块做法. 注意到我们是可以直接求单独某个k的矩阵,使用矩阵快速幂即可(取min的矩阵乘法). 单独求一次的 ...
随机推荐
- OpenOCD安装与使用(JTAG调试)
本文介绍openocd开源软件的安装以及搭配JTAG对Xilinx u500VC707devkit的调试 PC OS: Ubuntu20.04 LTS Target ARCH: riscv64 JTA ...
- 离散傅里叶变换DFT入门
网上对于傅里叶变换相关的文章很多(足够多),有的是从物理相关角度入场,有的从数学分析角度入场.对于有志学习相关概念的同学还是能够很好的理解的. 数学包括三大块:代数学.几何.数学分析.前两块我们在中学 ...
- [工作札记]02: .Net Winform控件TreeView最简递归绑定方法
前言:Treeview控件是我们在WinForm.WebForm开发中经常使用的控件,需要从数据库动态加载数据,然后递归绑定每一个节点:同样,递归的思路在其他程序中也经常运用,包括.Net MVC等. ...
- 简要MR与Spark在Shuffle区别
一.区别 ①本质上相同,都是把Map端数据分类处理后交由Reduce的过程. ②数据流有所区别,MR按map, spill, merge, shuffle, sort, r educe等各阶段逐一实现 ...
- nginx启动失败(bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket...permissions)
nginx启动失败 nginx启动失败(bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a ...
- 【Linux】自建回收站
linux rm命令是即刻删除的,而且挺多人喜欢加上-f强制命令,更暴力的是删除文件夹直接 rm -rf ,这样子代表你执行完后,就完全被干掉了. 还是推荐在linux下设置回收站,写一个shell脚 ...
- MySQL全面瓦解17:触发器相关
关于触发器 现实开发中我们经常会遇到这种情况,比如添加.删除和修改信息的时候需要记录日志,我们就要在完成常规的数据库逻辑操作之后再去写入日志表,这样变成了两步操作,更复杂了. 又比如删除一个人员信息的 ...
- Centos7.4 小白式安装(初学)
虚拟机安装Centos7.4系统 适用人群(初学者) 下载Centos7.4镜像 https://pan.baidu.com/s/1NtjfdHV3OWAvfDj5vrR7HQ 提取码:hzzw 虚 ...
- canvas性能-drawImage渲染图片
canvas性能-绘制图片 目录 canvas性能-绘制图片 canvas绘制图片 drawImage putImageData createPattern 测试绘制耗时 drawImage Imag ...
- LeetCode上并发题目无Go版本:台湾同胞试水 — 交替打印FooBar
https://mp.weixin.qq.com/s/I5va3PI1oGIj8R_n3Nw2yw