零食店

snackstore.in snackstore.out
时间限制:1 s 内存限制:256 MB
【题目描述】

成功找到了学长之后学姐感觉到有些饿,于是决定去附近的零食店给自己和学长买些零食。
焦作市的有n家零食店,由m条道路连接着这些零食店,每条道路都有自己的长度l,每家零食店都有自己的消费指数。
由于学姐是个穷B,所以去买零食的路上不能经过某些消费指数超过一定限度的店。
同时由于学姐体力有限,所以去买零食的过程中走的路程不能太长。
想来想去学姐决定去问学长买什么零食比较好,反正到最后都是学长吃╮(╯_╰)╭
在去问之前,学姐准备先做好准备,她把焦作市(所有零食店)的地图给了你,希望你能编出一个程序快速回答她从某个零食店出发,在上述限制下有多少家零食店可供她挑选。
【输入格式】
第一行三个正整数n,m,q,分别代表零食店数,道路数和询问数。
接下来一行n个正整数,第i个正整数vi代表第i家零食店的消费指数。
接下来m行,第i行三个正整数x,y,l,代表第i条道路连接编号为x和y的两个零食店,长度为l。
接下来q行第i行三个正整数s,c,d,代表第i个询问要求从s出发,所经过的零食店的消费指数不能超过c(除了起点和终点以外),且行走路程不超过d。
【输出格式】
一共q行,第i行一个整数代表在第i个询问的要求下有多少家零食店可供学姐挑选。
【样例输入】

5 5 2
1 2 3 4 5
1 2 1
1 3 4
2 3 2
1 4 3
2 5 1
1 1 3
2 1 2
【样例输出】
2
3
【提示】
样例中第一个询问能去编号为2/4的零食店。
第二个询问能去编号为1/3/5的零食店。
对于40%的数据,n≤10,m≤20,q=1。
对于70%的数据,m≤500,q≤10000。
对于100%的
数据,n≤100,m≤10000,q≤1000000,vi,c,d≤10^9,1≤x,y,s≤n,l≤10^6。

100
这道题应该让我对最短路的理解更深了,基本想法和标解一样,但很可惜
最短路写不出来233

70%的数据量点数边数和询问数都比较小,每次询问时去掉不符合条件的点(但仍要计算出这些点的dis值,只是不用这些点进行三角形迭代)后使用任意单源最短路算法解决即可。
消费指数的限制对应只能经过消费指数排名前几的点,而路径长度的限制对应只能抵达最短路排名前几的点,所以我们考虑能不能预处理出g[k][i][j]代表从i出发只经过消费指数前k的点,距离i第j短的点距离为多少,这样的话每次询问只需要二分出k,然后在g[k][i]数组中二分就可以了。
预处理时我们可以当做动态加点的全源最短路,我们用动态规划的转移方程表示这个过程:用f[k][i][j]代表i出发只经过消费指数前k的点,i到j的最短路为多少。
f[k][i][j]=min{f[k-1][i][j],f[k-1][i][v[k]]+f[k-1][v[k]][j]}(其中v[k]代表消费指数排第k的点,1≤i,j≤n)
而f[0]数组很显然就是这个图的邻接矩阵。
求出f数组之后将所有f[k][i]数组排序就是上面所求的g数组了,询问的时候加两个二分即可,时间复杂度为O(n^3logn+qlognn),没有可以去卡不排序每次询问在f数组中枚举的算法,但是泥萌要知道这个做法有优化的空间。
聪明的小朋友们已经看出来了上面这个动态规划就是floyd算法。
有很多算法都是实现简单但是想要深入理解起来并不简单的,比如floyd/FFT/FWT/后缀自动机等,希望大家在学算法的时候要理解得透彻一些,不要再碰到模板题还不会写了。

梁哥的做法,我觉得更好,k在Floyd中的作用是松弛,那么可以对查询按照c排序,每次取不大于c的k接着上一次的dis继续做,这样的结果其实就是一边Floyd。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值