kruskal 重构树
对于一张无向图,我们在进行 kruskal 的过程中
每当合并两个联通块时
新建虚拟节点 t
对于两个联通块的根节点 fau,fav 连无向边
(fau, t),(fav, t) 其中点 t 的点权为两个联通块当前连边的边权
对于这道题
首先 dijkstra 处理所有点到1号点的最短路
然后按照边的海拔进行降序排序
这样做出重构树之后
显然对于点 u,它的所有子树中的相关的边的海拔(这里已经转化为了虚拟节点的点权)都要大于该点的海拔
这样的话
对于询问二元组 x, h
倍增将 x 调到海拔最低且高于 h 的点处
此时 x 的子树中dis[]的最小值即为此次询问的结果
注意:在进行重构树时
虚拟节点的dis[]每次可以取 min(dis[fau], dis[fav])
这样就相当于dis[t]表示 t 的子树中dis[]的最小值
省去了一遍 dfs

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <queue>
  5. #include <cstring>
  6.  
  7. using namespace std;
  8. const int N = 4e5 + , oo = 1e9 + ;
  9.  
  10. struct Node {
  11. int u, v, len, high, nxt;
  12. } E[N], G[N << ], Edge[N << ];
  13. struct Node_ {
  14. int u, dis_;
  15. inline bool operator < (const Node_ a) const {return dis_ > a.dis_;}
  16. };
  17.  
  18. int head_1[N], head_2[N << ], now;
  19. int dis[N << ];
  20. bool vis[N];
  21. int fa[N << ];
  22. int n, m;
  23. int High[N << ];
  24. int f[N << ][];
  25. int deep[N << ];
  26.  
  27. #define gc getchar()
  28. inline int read() {
  29. int x = ;
  30. char c = gc;
  31. while(c < '' || c > '') c = gc;
  32. while(c >= '' && c <= '') x = x * + c - '', c = gc;
  33. return x;
  34. }
  35.  
  36. int Get(int x) {return fa[x] == x ? x : fa[x] = Get(fa[x]);}
  37. inline bool Cmp(Node a, Node b) {return a.high > b.high;}
  38. void Dfs(int u, int fa) {for(int i = head_2[u]; ~ i; i = G[i].nxt) if(G[i].v != fa) f[G[i].v][] = u, Dfs(G[i].v, u);}
  39. inline int Jump(int X, int H) {for(int i = ; i >= ; i --) if(f[X][i] && High[f[X][i]] > H) X = f[X][i];return X;}
  40. inline void Add_Edge(int u, int v, int Len) {Edge[++ now].v = v; Edge[now].len = Len; Edge[now].nxt = head_1[u]; head_1[u] = now;}
  41. inline void Add_G(int u, int v) {G[++ now].v = v; G[now].nxt = head_2[u]; head_2[u] = now;}
  42. inline void Pre() {for(int i = ; i <= ; i ++) for(int j = ; j <= (n * - ); j ++) f[j][i] = f[f[j][i - ]][i - ];}
  43.  
  44. inline void Dijkstra() {
  45. for(int i = ; i <= n; i ++) dis[i] = oo;
  46. for(int i = ; i <= n; i ++) vis[i] = ;
  47. priority_queue <Node_> Q;
  48. Q.push((Node_) {, });
  49. dis[] = ;
  50. while(!Q.empty()) {
  51. Node_ topp = Q.top();
  52. Q.pop();
  53. if(vis[topp.u]) continue;
  54. vis[topp.u] = ;
  55. for(int i = head_1[topp.u]; ~ i; i = Edge[i].nxt)
  56. if(dis[Edge[i].v] > dis[topp.u] + Edge[i].len) {
  57. dis[Edge[i].v] = dis[topp.u] + Edge[i].len;
  58. Q.push((Node_) {Edge[i].v, dis[Edge[i].v]});
  59. }
  60. }
  61. }
  62.  
  63. inline void Kruskal() {
  64. sort(E + , E + m + , Cmp);
  65. for(int i = ; i <= (n << ); i ++) fa[i] = i;
  66. for(int i = ; i <= (n << ); i ++) head_2[i] = -;
  67. int cnt = n;
  68. now = ;
  69. for(int i = ; i <= m; i ++) {
  70. if(cnt == n * - ) break;
  71. int u = E[i].u, v = E[i].v, fau = Get(u), fav = Get(v);
  72. if(fau != fav) {
  73. fa[fau] = fa[fav] = ++ cnt;
  74. High[cnt] = E[i].high;
  75. dis[cnt] = min(dis[fau], dis[fav]);
  76. Add_G(fau, cnt), Add_G(cnt, fau), Add_G(fav, cnt), Add_G(cnt, fav);
  77. }
  78. }
  79. }
  80.  
  81. int main() {
  82. for(int T = read(); T; T --) {
  83. memset(f, , sizeof f);
  84. n = read(), m = read(); now = ;
  85. for(int i = ; i <= n; i ++) head_1[i] = -;
  86. for(int i = ; i <= m; i ++) {
  87. int u = read(), v = read(), Len = read(), high = read();
  88. Add_Edge(u, v, Len), Add_Edge(v, u, Len);
  89. E[i] = (Node) {u, v, Len, high};
  90. }
  91. Dijkstra(), Kruskal(), Dfs( * n - , ), Pre();
  92. int Q = read(), K = read(), S = read(), Lastans = ;
  93. for(; Q; Q --) {
  94. int X = (read() + K * Lastans - ) % n + , H = (read() + K * Lastans) % (S + );
  95. Lastans = dis[Jump(X, H)]; cout << Lastans << "\n";
  96. }
  97. }
  98. return ;
  99. }

luogu 4768的更多相关文章

  1. Luogu 4768 [NOI2018]归程

    并不会写Kruskal重构树,两个$log$跑得比较卡. 首先考虑一下没有强制在线的要求怎么办,有一个比较容易想到的做法就是先跑一遍最短路,然后把所有边按照海拔从大到小排序,把所有询问的海拔也从大到小 ...

  2. Luogu 魔法学院杯-第二弹(萌新的第一法blog)

    虽然有点久远  还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题  沉迷游戏,伤感情 #include <queue> ...

  3. luogu p1268 树的重量——构造,真正考验编程能力

    题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...

  4. [luogu P2170] 选学霸(并查集+dp)

    题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一 ...

  5. [luogu P2647] 最大收益(贪心+dp)

    题目传送门:https://www.luogu.org/problem/show?pid=2647 题目描述 现在你面前有n个物品,编号分别为1,2,3,--,n.你可以在这当中任意选择任意多个物品. ...

  6. HDU 4768 Flyer(二分法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4768 题目大意:每组数据有n行输入,每行有三个数A.B.C,A<=B且小于2^32,从A到B每隔 ...

  7. Codevs 4768 跳石头 NOIP2015 DAY2 T1

    4768 跳石头 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 传送门 题目描述 Description 一年一度的"跳石头"比赛又要开始了! ...

  8. Luogu 考前模拟Round. 1

    A.情书 题目:http://www.luogu.org/problem/show?pid=2264 赛中:sb题,直接暴力匹配就行了,注意一下读入和最后一句话的分句 赛后:卧槽 怎么只有40 B.小 ...

  9. luogu P2580 于是他错误的点名开始了

    luogu  P2580 于是他错误的点名开始了 https://www.luogu.org/problem/show?pid=2580 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边 ...

随机推荐

  1. 【hash】Similarity of Subtrees

    图片来源: https://blog.csdn.net/dylan_frank/article/details/78177368 [题意]: 对于每一个节点来说有多少对相同的子树. [题解]: 利用层 ...

  2. scratch少儿编程第一季——06、人在江湖混,没有背景怎么行。

    各位小伙伴大家好: 到上期我们学习了动作模块的全部指令.接下我们用动作模块做一个小小项目,来总结我们前面学的内容. 在做项目之前我们先来换一个背景. 在左下角舞台区,点击打开背景库,选择自己所需要的背 ...

  3. 奇妙的算法【7】-贪婪算法-dp

    问题1描述:[贪婪算法,Dijistra算法] ①有一只兔子要从一个N*N的二维矩阵方格中从上跳到下面: ②每次只能向左或向下,越过一个方格,跳到下一个方格中: ③被越过的方格中的数值,表示该兔子越过 ...

  4. 数据仓库之抽取数据:openrowset函数带bulk操作符的用法

    原文:数据仓库之抽取数据:openrowset函数带bulk操作符的用法 在做数据仓库时,最重要的就是ETL的开发,而在ETL开发中的第一步,就是要从原OLTP系统中抽取数据到过渡区中,再对这个过渡区 ...

  5. C#通过重载构造函数传递参数、实现两个窗体下的方法的互相调用

    直接切入主题 有时候同一个项目下我们可能会使用多个窗体,窗体间方法互相调用也不可避免,好了,使用无参无返回值的方法,开始上图 1.新建一个winform项目Form1,并再添加一个窗体Form2:拖入 ...

  6. koa2中间件学习笔记

    洋葱模型 整个洋葱就是服务端程序app,每层洋葱皮都是一个中间件,传入requrest,经过各个中间件处理之后传出response. 新建中间件m1.js,m2.js koa-learn/middle ...

  7. python常见函数运用【一】

    1.Python hasattr() 函数 描述hasattr() 函数用于判断对象是否包含对应的属性. 语法 hasattr 语法: hasattr(object, name)参数object -- ...

  8. Golang内存管理

    Golang 内存管理 原文链接[http://legendtkl.com/2017/04/02/golang-alloc/] Golang 的内存管理基于 tcmalloc,可以说起点挺高的.但是 ...

  9. stm32 按键操作

    抖动时间的长短由按键的机械特性决定,一般为5ms-10ms void key() { static u8 flag = 1; if(flag == 1 && KEY_UP == 1) ...

  10. Linux报错排解

    1.Loaded plugins: product-id, search-disabled-repos, subscription-manager This system is not registe ...