考虑枚举加油的位置,当确定某次在第$i$个位置加油后,且下一次到$j$加油,那么$i$到$j$必然会选择不超过$c_{i}$条边且最长的路径,记作$d_{i,j}$

如果能求出$d_{i,j}$,再设$f_{q,i}$表示$q$元(恰好用完)从$i$出发的最长路,枚举$i$之后那一次加油点即可转移,由于$q\le n^{2}$,因此这里的复杂度为$o(n^{4})$

接下来,对其求一次前缀max再二分,即可对询问做到$o(t\log_{2}q)$的复杂度

现在还有一个问题,考虑如何预处理最开始的$d_{i,j}$

倍增,求出从$i$出发,走不超过$2^{k}$次走到$j$的最长路,通过枚举走$2^{k-1}$时的点来转移,可以做到$o(n^{3}\log_{2}c_{i})$

类似的,再对每一个点$i$做一次dp,同样枚举中专点转移即可,时间复杂度也是$o(n^{3}\log_{2}c_{i})$

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 105
  4. 4 #define M 1005
  5. 5 #define K 100005
  6. 6 struct ji{
  7. 7 int nex,to,len;
  8. 8 }edge[M];
  9. 9 struct qu{
  10. 10 int s,q,d;
  11. 11 }q[K];
  12. 12 int E,n,m,t,x,y,z,head[N],p[N],c[N],g[21][N][N],ff[N],f[N][N],ans[N*N][N];
  13. 13 void add(int x,int y,int z){
  14. 14 edge[E].nex=head[x];
  15. 15 edge[E].to=y;
  16. 16 edge[E].len=z;
  17. 17 head[x]=E++;
  18. 18 }
  19. 19 int main(){
  20. 20 scanf("%d%d%d%d",&n,&m,&c[0],&t);
  21. 21 for(int i=1;i<=n;i++){
  22. 22 scanf("%d%d",&p[i],&c[i]);
  23. 23 c[i]=min(c[i],c[0]);
  24. 24 if (!p[i]){
  25. 25 printf("orz");
  26. 26 return 0;
  27. 27 }
  28. 28 }
  29. 29 memset(head,-1,sizeof(head));
  30. 30 for(int i=1;i<=m;i++){
  31. 31 scanf("%d%d%d",&x,&y,&z);
  32. 32 add(x,y,z);
  33. 33 }
  34. 34 memset(g,-0x3f,sizeof(g));
  35. 35 for(int i=1;i<=n;i++){
  36. 36 g[0][i][i]=0;
  37. 37 for(int j=head[i];j!=-1;j=edge[j].nex)g[0][i][edge[j].to]=max(g[0][i][edge[j].to],edge[j].len);
  38. 38 }
  39. 39 for(int i=1;i<=20;i++)
  40. 40 for(int x=1;x<=n;x++)
  41. 41 for(int y=1;y<=n;y++)
  42. 42 for(int z=1;z<=n;z++)
  43. 43 g[i][x][y]=max(g[i][x][y],g[i-1][x][z]+g[i-1][z][y]);
  44. 44 memset(f,-1,sizeof(f));
  45. 45 for(int i=1;i<=n;i++)f[i][i]=0;
  46. 46 for(int x=1;x<=n;x++)
  47. 47 for(int i=0;i<=20;i++)
  48. 48 if (c[x]&(1<<i)){
  49. 49 for(int y=1;y<=n;y++)ff[y]=f[x][y];
  50. 50 for(int y=1;y<=n;y++)
  51. 51 for(int z=1;z<=n;z++)
  52. 52 if (ff[z]!=-1)f[x][y]=max(f[x][y],ff[z]+g[i][z][y]);
  53. 53 }
  54. 54 memset(ans,-0x3f,sizeof(ans));
  55. 55 for(int i=1;i<=n;i++)ans[0][i]=0;
  56. 56 for(int i=1;i<=n*n;i++)
  57. 57 for(int x=1;x<=n;x++)
  58. 58 if (p[x]<=i)
  59. 59 for(int y=1;y<=n;y++)
  60. 60 if (f[x][y]!=-1)ans[i][x]=max(ans[i][x],ans[i-p[x]][y]+f[x][y]);//o(n^4)
  61. 61 for(int i=1;i<=n*n;i++)
  62. 62 for(int j=1;j<=n;j++)ans[i][j]=max(ans[i][j],ans[i-1][j]);
  63. 63 for(int i=1;i<=t;i++){
  64. 64 scanf("%d%d%d",&x,&y,&z);
  65. 65 if (ans[y][x]<z)printf("-1\n");
  66. 66 else{
  67. 67 int l=0,r=y;
  68. 68 while (l<r){
  69. 69 int mid=(l+r>>1);
  70. 70 if (ans[mid][x]>=z)r=mid;
  71. 71 else l=mid+1;
  72. 72 }
  73. 73 printf("%d\n",y-l);
  74. 74 }
  75. 75 }
  76. 76 return 0;
  77. 77 }

[loj539]旅游路线的更多相关文章

  1. 「LibreOJ NOIP Round #1」旅游路线

    Description T 城是一个旅游城市,具有 nnn 个景点和 mmm 条道路,所有景点编号为 1,2,...,n1,2,...,n1,2,...,n.每条道路连接这 nnn 个景区中的某两个景 ...

  2. [solution]JZOJ-5838 旅游路线

    [solution] JZOJ-5838 旅游路线 Time Limits 1000ms,Memory Limits 128MB 题面 Description GZOI队员们到X镇游玩.X镇是一个很特 ...

  3. JZOJ 5838. 旅游路线 最大子段和

    5838. 旅游路线 Time Limits: 1000 ms  Memory Limits: 131072 KB  Detailed Limits   Goto ProblemSet Descrip ...

  4. [loj#539][LibreOJ NOIP Round #1]旅游路线_倍增_dp

    「LibreOJ NOIP Round #1」旅游路线 题目链接:https://loj.ac/problem/539 题解: 这个题就很神奇 首先大力$dp$很好想,因为可以把一维放到状态里以取消后 ...

  5. 带你找到五一最省的旅游路线【dijkstra算法推导详解】

    前言 五一快到了,小张准备去旅游了! 查了查到各地的机票 因为今年被扣工资扣得很惨,小张手头不是很宽裕,必须精打细算.他想弄清去各个城市的最低开销. [嗯,不用考虑回来的开销.小张准备找警察叔叔说自己 ...

  6. 带你找到五一最省的旅游路线【dijkstra算法代码实现】

    算法推导过程参见[dijkstra算法推导详解] 此文为[dijkstra算法代码实现] https://www.cnblogs.com/Halburt/p/10767389.html package ...

  7. LibreOJ #539. 「LibreOJ NOIP Round #1」旅游路线(倍增+二分)

    哎一开始看错题了啊T T...最近状态一直不对...最近很多傻逼题都不会写了T T 考虑距离较大肯定不能塞进状态...钱数<=n^2能够承受, 油量再塞就不行了...显然可以预处理出点i到j走c ...

  8. 【LibreOJ】#539. 「LibreOJ NOIP Round #1」旅游路线

    [题意]给定正边权有向图,车油量上限C,每个点可以花费pi加油至min(C,ci),走一条边油-1,T次询问s点出发带钱q,旅行路程至少为d的最多剩余钱数. n<=100,m<=1000, ...

  9. LOJ#539. 「LibreOJ NOIP Round #1」旅游路线

    n<=100,m<=1000的图,在此图上用油箱容量C<=1e5的车来旅行,旅行时,走一条边会耗一单伟油,在点i时,若油量<ci,则可以把油以pi的价格补到ci,pi<= ...

随机推荐

  1. 文本域textarea的一个小细节

    文本域代码在编写时,最好写在一行上,就像: 如果没写在一行上,如: 那么就会在后续生成的页面上输入的时候就会产生一段空白无法删除: 这是写文本框的时候的一个小细节

  2. Android构建工具--AAPT2源码解析(一)

    一.什么是AAPT2 在Android开发过程中,我们通过Gradle命令,启动一个构建任务,最终会生成构建产物"APK"文件.常规APK的构建流程如下: (引用自Google官方 ...

  3. 第二次Scrum Metting

    日期:2021年4月25日会议主要内容概述:前后端针对WebAPI进行协调与统一工作,商量接下来两日计划:敲定部分设计细节. 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中 ...

  4. Scrum Meeting 0529

    零.说明 日期:2021-5-29 任务:简要汇报七日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 七日内已完成的任务 后两日计划完成的任务 困难 qsy PM&前端 完成后端管 ...

  5. Beta阶段第七次会议

    Beta阶段第七次会议 时间:2020.5.23 完成工作 姓名 工作 难度 完成度 ltx 1.修改小程序页面无法加载bug2.修改条件语句,使得页面能够正常显示 中 90% xyq 1.根据api ...

  6. 问题:两个对象值相同(x.equals(y) == true),但是可能存在hashCode不同吗?

    面试官的考察点 这道题仍然是考察JVM层面的基本知识,面试官认为,基本功扎实,才能写出健壮性和稳定性很高的代码. 涉及到的技术知识 (x.equals(y)==true),这段代码,看起来非常简单,但 ...

  7. 简明教程 | Docker篇 · 其一:基础入门

    了解Docker Docker是什么 Docker是指容器化技术,用于支持创建和使用 Linux 容器,同时Docker也是软件容器平台. 什么是容器(container) 容器是主机上与其他进程隔离 ...

  8. UVA-1016 Silly Sort

    UVA-1016 题目大意:给定一个长度为n的序列,每次操作可以交换任意两个数的位置,代价为两个数的和,求最小代价,将序列排成有序的. 首先,显然需要交换的数一定会形成环: 那么对于每一个环,我们有两 ...

  9. 关于QGIS的插件开发(C++)

    关于C++插件的开发材料较少,根据网上的指导,我采用了早期版本的插件模板生成的方法来创建QGIS的插件,其方法是从以前版本(2.18.25)里面拷贝插件模板的方法进行,具体的执行步骤为 1.拷贝文件 ...

  10. 『学了就忘』Linux基础 — 15、了解Linux系统的目录结构

    目录 1.一级目录说明 (1)一级目录列表 (2)/bin/和/sbin/目录说明 (3)/boot/目录说明 (4)/lib/和/lib64/目录说明 (5)/lost+found/目录说明 (6) ...