[LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程

题意

给定一张无向图, 每条边有一个距离和一个高度. 再给定 \(q\) 组可能在线的询问, 每组询问给定一个点 \(v\) 和一个高度 \(h\), 鸭子德可以先无需花费地在高度大于 \(h\) 的边上任意行动, 然后可以在任意点开始以花费等于距离的模式行动. 问最小的花费.

\(|V|\le 2\times 10^5,|E|\le 4\times 10^5,q\le 4\times 10^5,h\le 10^9\).

题解

显然带花费部分的行动是一个单源最短路. 那么我们只要求出无花费部分的行动可以到达的点中哪一个点距离 \(1\) 最近就可以了.

发现无花费部分是个类似瓶颈路的问题, 我们可以在 Kruskal 重构树上倍增求出能到达的点所组成的子树, 输出这个子树中的点到 \(1\) 的最短距离就可以了.

为啥我要写这个裸题的题解呢?

一个原因是存板子, 另一个原因是这个沙雕强制在线把我卡掉了 \(3\) 分qaq...具体情况

参考代码

  1. #include <bits/stdc++.h>
  2. const int MAXV=4e5+10;
  3. const int MAXE=1e6+10;
  4. struct Edge{
  5. int from;
  6. int to;
  7. int dis;
  8. int pos;
  9. Edge* next;
  10. bool friend operator>(const Edge& a,const Edge& b){
  11. return a.pos>b.pos;
  12. }
  13. };
  14. Edge E[MAXE];
  15. Edge Ex[MAXE];
  16. Edge* head[MAXV];
  17. Edge* top=E;
  18. int v;
  19. int e;
  20. int q;
  21. int n;
  22. int k;
  23. int maxv;
  24. int dis[MAXV];
  25. int pos[MAXV];
  26. int ufs[MAXV];
  27. bool vis[MAXV];
  28. int pprt[20][MAXV];
  29. int* prt=pprt[0];
  30. int ReadInt();
  31. void Kruskal();
  32. int FindRoot(int);
  33. void Dijkstra(int);
  34. void Insert(int,int,int,int);
  35. int main(){
  36. int T=ReadInt();
  37. while(T--){
  38. memset(pprt,0,sizeof(pprt));
  39. memset(head,0,sizeof(head));
  40. memset(vis,0,sizeof(vis));
  41. top=E;
  42. n=v=ReadInt();
  43. e=ReadInt();
  44. for(int i=0;i<e;i++){
  45. int a=ReadInt(),b=ReadInt(),c=ReadInt(),d=ReadInt();
  46. Ex[i]=Edge({a,b,c,d,NULL});
  47. Insert(a,b,c,d);
  48. Insert(b,a,c,d);
  49. }
  50. q=ReadInt(),k=ReadInt(),maxv=ReadInt();
  51. Dijkstra(1);
  52. Kruskal();
  53. int lg=0;
  54. for(int i=1;(1<<i)<=v;i++){
  55. lg=i;
  56. for(int j=1;j<=v;j++)
  57. pprt[i][j]=pprt[i-1][pprt[i-1][j]];
  58. }
  59. int lastans=0;
  60. while(q--){
  61. int s=(0ll+ReadInt()+k*lastans-1)%n+1,h=(0ll+ReadInt()+k*lastans)%(maxv+1);
  62. for(int i=lg;i>=0;i--){
  63. if(pos[pprt[i][s]]>h)
  64. s=pprt[i][s];
  65. }
  66. printf("%d\n",lastans=dis[s]);
  67. }
  68. }
  69. return 0;
  70. }
  71. void Kruskal(){
  72. std::sort(Ex,Ex+e,std::greater<Edge>());
  73. for(int i=1;i<=v;i++)
  74. ufs[i]=i;
  75. int& cur=v;
  76. for(int i=0;i<e;i++){
  77. int a=FindRoot(Ex[i].from);
  78. int b=FindRoot(Ex[i].to);
  79. if(a!=b){
  80. ++cur;
  81. pos[cur]=Ex[i].pos;
  82. dis[cur]=std::min(dis[a],dis[b]);
  83. prt[a]=cur;
  84. prt[b]=cur;
  85. ufs[cur]=cur;
  86. ufs[a]=cur;
  87. ufs[b]=cur;
  88. }
  89. }
  90. }
  91. void Dijkstra(int s){
  92. std::priority_queue<std::pair<int,int>> q;
  93. memset(dis,0x7F,sizeof(dis));
  94. dis[s]=0;
  95. q.emplace(0,s);
  96. while(!q.empty()){
  97. s=q.top().second;
  98. q.pop();
  99. if(vis[s])
  100. continue;
  101. vis[s]=true;
  102. for(Edge* i=head[s];i!=NULL;i=i->next){
  103. if(dis[i->to]>dis[s]+i->dis){
  104. dis[i->to]=dis[s]+i->dis;
  105. q.emplace(-dis[i->to],i->to);
  106. }
  107. }
  108. }
  109. }
  110. inline void Insert(int from,int to,int dis,int pos){
  111. top->from=from;
  112. top->to=to;
  113. top->dis=dis;
  114. top->pos=pos;
  115. top->next=head[from];
  116. head[from]=top++;
  117. }
  118. int FindRoot(int x){
  119. return ufs[x]==x?ufs[x]:ufs[x]=FindRoot(ufs[x]);
  120. }
  121. inline int ReadInt(){
  122. int x=0;
  123. register char ch=getchar();
  124. while(!isdigit(ch))
  125. ch=getchar();
  126. while(isdigit(ch)){
  127. x=x*10+ch-'0';
  128. ch=getchar();
  129. }
  130. return x;
  131. }

[LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程的更多相关文章

  1. [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士

    [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士 题意 题面好啰嗦啊直接粘LOJ题面好了 小 D 最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照 ...

  2. [LOJ 2134][UOJ 132][BZOJ 4200][NOI 2015]小园丁与老司机

    [LOJ 2134][UOJ 132][BZOJ 4200][NOI 2015]小园丁与老司机 题意 给定平面上的 \(n\) 个整点 \((x_i,y_i)\), 一共有两个问题. 第一个问题是从原 ...

  3. [LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会

    [LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会 题意 给定一个长度为 \(n\) 的字符串 \(s\), 对于所有 \(r\in[1,n]\) 求出 \(s\ ...

  4. [LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分

    [LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分 题意 给定一个字符串 \(S\), 求有多少种将 \(S\) 的子串拆分为形如 AABB 的拆分方案 \(| ...

  5. [NOI 2018] 归程

    Description 传送门 Solution 65分做法 先求出每个点到\(1\)号点的最短路,记为\(d[i]\).然后按照海拔从大到小依次加边,并查集维护每个连通块中\(d[i]\)的最小值, ...

  6. 解题:NOI 2018 归程

    题面 清新友好的题目 跑一个最短路,然后对海拔建Kruskal重构树,从最后接上去的边(最低的一个)开始DFS一下处理子树里路程的最小值. 询问是每次在重构树上倍增找到深度最浅的海拔高于当天水位线的节 ...

  7. NOI 2018 归程 (Kruskal重构树)

    题目大意:太长了,略 Kruskal重构树,很神奇的一个算法吧 如果两个并查集被某种条件合并,那么这个条件作为一个新的节点连接两个并查集 那么在接下来的提问中,如果某个点合法,它的所有子节点也都合法, ...

  8. [LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字

    [LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字 题意 给定一个大串 \(S\) 以及 \(q\) 次询问, 每次询问给定一个串 \(T\) 和区间 \([l, ...

  9. UOJ #449. 【集训队作业2018】喂鸽子

    UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...

随机推荐

  1. 第02组 Beta版本演示

    目录 1. 博客链接及组员信息(2分) 2. 贡献比例(3分) 3. GitHub 项目链接(1分) 4. 博客汇总(2分) 5. 燃尽图(3分) 6. 原计划.达成情况及原因分析(6分) 7. Be ...

  2. vscode源码分析【三】程序的启动逻辑,性能问题的追踪

    第一篇: vscode源码分析[一]从源码运行vscode 第二篇:vscode源码分析[二]程序的启动逻辑,第一个窗口是如何创建的 启动追踪 代码文件:src\main.js 如果指定了特定的启动参 ...

  3. 融云技术分享:解密融云IM产品的聊天消息ID生成策略

    本文来自融云技术团队原创分享,原文发布于“融云全球互联网通信云”公众号,原题<如何实现分布式场景下唯一 ID 生成?>,即时通讯网收录时有部分改动. 1.引言 对于IM应用来说,消息ID( ...

  4. SpringBoot系列之@PropertySource用法简介

    SpringBoot系列之@PropertySource用法简介 继上篇博客:SpringBoot系列之@Value和@ConfigurationProperties用法对比之后,本博客继续介绍一下@ ...

  5. git分支合并解决冲突

    git分支合并,解决冲突 1.手动解决冲突 手动解决冲突,需要使用编辑器,把所有文件中出现的冲突地方修改,然后再添加到暂存区再提交 >>>>>>brancha so ...

  6. 基于 HTML5 WebGL 的 3D 科幻风机

    前言 许多世纪以来,风力机同水力机械一样,作为动力源替代人力.畜力,对生产力的发展发挥过重要作用.近代机电动力的广泛应用以及二十世纪50年代中东油田的发现,使风机发电机的发展缓慢下来. 70年代初期, ...

  7. JXL工具包对Excle文件操作

    1.简介: XL - JXL(Java Excel API)是一个用来动态读写 Excel 文件的开源框架,利用它可以 在任何支持 Java 的操作系统上动态读写 Excel 文件. 2.开发步骤 1 ...

  8. 最近的项目系之3——core3.0整合Senparc

    1.前言 既然是.net下微信开发,自然少不了Senparc,可以说这个框架的存在, 至少节省了微信相关工作量的80%.事实上,项目开始前,还纠结了下是Java还是core,之所以最终选择core,除 ...

  9. 通过Desktop.ini设置文件夹备注以及图标

    1.新建一个文件夹temp,进入此文件夹,建立desktop.ini文件,编辑内容为: ; 文件夹图标 [.ShellClassInfo] ;设置文件夹的备注 InfoTip=this is temp ...

  10. TOTP算法实现二步验证

    概念 TOTP算法(Time-based One-time Password algorithm)是一种从共享密钥和当前时间计算一次性密码的算法. 它已被采纳为Internet工程任务组标准RFC 6 ...