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

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>using namespace std;
const int N = 4e5 + 10, oo = 1e9 + 7;struct Node {int u, v, len, high, nxt;
} E[N], G[N << 2], Edge[N << 1];
struct Node_ {int u, dis_;inline bool operator < (const Node_ a) const {return dis_ > a.dis_;}
};int head_1[N], head_2[N << 1], now;
int dis[N << 1];
bool vis[N];
int fa[N << 1];
int n, m;
int High[N << 1];
int f[N << 1][30];
int deep[N << 1];#define gc getchar()
inline int read() {int x = 0;char c = gc;while(c < '0' || c > '9') c = gc;while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;return x;
}int Get(int x) {return fa[x] == x ? x : fa[x] = Get(fa[x]);}
inline bool Cmp(Node a, Node b) {return a.high > b.high;}
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][0] = u, Dfs(G[i].v, u);}
inline int Jump(int X, int H) {for(int i = 20; i >= 0; i --) if(f[X][i] && High[f[X][i]] > H) X = f[X][i];return X;}
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;}
inline void Add_G(int u, int v) {G[++ now].v = v; G[now].nxt = head_2[u]; head_2[u] = now;}
inline void Pre() {for(int i = 1; i <= 20; i ++) for(int j = 1; j <= (n * 2 - 1); j ++) f[j][i] = f[f[j][i - 1]][i - 1];}inline void Dijkstra() {for(int i = 1; i <= n; i ++) dis[i] = oo;for(int i = 1; i <= n; i ++) vis[i] = 0;priority_queue <Node_> Q;Q.push((Node_) {1, 0});dis[1] = 0;while(!Q.empty()) {Node_ topp = Q.top();Q.pop();if(vis[topp.u]) continue;vis[topp.u] = 1;for(int i = head_1[topp.u]; ~ i; i = Edge[i].nxt)if(dis[Edge[i].v] > dis[topp.u] + Edge[i].len) {dis[Edge[i].v] = dis[topp.u] + Edge[i].len;Q.push((Node_) {Edge[i].v, dis[Edge[i].v]});}}
}inline void Kruskal() {sort(E + 1, E + m + 1, Cmp);for(int i = 1; i <= (n << 1); i ++) fa[i] = i;for(int i = 1; i <= (n << 1); i ++) head_2[i] = -1;int cnt = n;now = 0;for(int i = 1; i <= m; i ++) {if(cnt == n * 2 - 1) break;int u = E[i].u, v = E[i].v, fau = Get(u), fav = Get(v);if(fau != fav) {fa[fau] = fa[fav] = ++ cnt;High[cnt] = E[i].high;dis[cnt] = min(dis[fau], dis[fav]);Add_G(fau, cnt), Add_G(cnt, fau), Add_G(fav, cnt), Add_G(cnt, fav);}}
}int main() {for(int T = read(); T; T --) {memset(f, 0, sizeof f);n = read(), m = read(); now = 0;for(int i = 1; i <= n; i ++) head_1[i] = -1;for(int i = 1; i <= m; i ++) {int u = read(), v = read(), Len = read(), high = read();Add_Edge(u, v, Len), Add_Edge(v, u, Len);E[i] = (Node) {u, v, Len, high};}Dijkstra(), Kruskal(), Dfs(2 * n - 1, 0), Pre();int Q = read(), K = read(), S = read(), Lastans = 0;for(; Q; Q --) {int X = (read() + K * Lastans - 1) % n + 1, H = (read() + K * Lastans) % (S + 1);Lastans = dis[Jump(X, H)]; cout << Lastans << "\n";}}return 0;
}

转载于:https://www.cnblogs.com/shandongs1/p/9497615.html

luogu 4768相关推荐

  1. luogu P1549 棋盘问题(2) 题解

    luogu P1549 棋盘问题(2) 题解 题目描述 在\(N * N\)的棋盘上\((1≤N≤10)\),填入\(1,2,-,N^2\)共\(N^2\)个数,使得任意两个相邻的数之和为素数. 例如 ...

  2. [Luogu] 选学霸

    https://www.luogu.org/problemnew/show/P2170 并查集+DP #include <iostream> #include <cstring> ...

  3. Luogu 2470 [SCOI2007]压缩

    和Luogu 4302 [SCOI2003]字符串折叠 差不多的想法,区间dp 为了计算方便,我们可以假设区间[l, r]的前面放了一个M,设$f_{i, j, 0/1}$表示区间$[i, j]$中是 ...

  4. 【Luogu】P1613 跑路

    [Luogu]P1613 跑路 一.题目 题目描述 小A的工作不仅繁琐,更有苛刻的规定,要求小A每天早上在6:00之前到达公司,否则这个月工资清零.可是小A偏偏又有赖床的坏毛病.于是为了保住自己的工资 ...

  5. Luogu P6055 [RC-02] GCD(莫比乌斯反演,杜教筛)(这题乐死我了,真就图一乐呗)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Weblink https://www.luogu.com.cn/problem/P6055 Prob ...

  6. Luogu P3177 [HAOI2015] 树上染色(树上背包)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Luogu P3177 [HAOI2015] 树上染色 有一棵点数为 NNN 的树,树边有边权.给你一 ...

  7. Luogu P4178 Tree (点分治 + 树状数组)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Weblink https://www.luogu.com.cn/problem/P4178 Prob ...

  8. Luogu P4336 [SHOI2016]黑暗前的幻想乡(容斥,矩阵树定理,子集反演)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Luogu P4336 [SHOI2016]黑暗前的幻想乡(容斥,矩阵树定理) Problem n≤1 ...

  9. BZOJ 2154 [国家集训队]Crash的数字表格 / JZPTAB(莫比乌斯反演,经典好题)(Luogu P1829)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 P1829 [国家集训队]Crash的数字表格 / JZPTAB(反演,经典好题) Problem S ...

最新文章

  1. 【J2SE】语言基础
  2. Kubernetes Service 对象的使用
  3. statistics_level参数的介绍
  4. 第3章-动态基础分析实验
  5. C++中的接口继承和实现继承
  6. 实验2-2-7 整数四则运算 (10 分)
  7. [HAOI2006]聪明的猴子
  8. hive 复合结构Map、Struct详解
  9. 软件测试基础知识整理(详细版)
  10. Unity Koreographer 之 音乐制作插件介绍学习,一般使用步骤介绍(包括:一般音乐游戏制作流程简绍) 一
  11. 【工具推荐】之桌面软件
  12. python网课答案查询_网课答案查询助手v1.0 官方版
  13. ArduinoUNO驱动RGB模块全彩效果示例
  14. allegro隐藏/显示铜皮
  15. 微信小程序开发页面介绍
  16. BIGEMAP如何添加在线第三方地图
  17. MySQL数据库(1):数据库 Database 基本概念
  18. android 设置软键盘高度,Android 软键盘一招搞定(实践篇)
  19. bzoj3939 [Usaco2015 Feb]Cow Hopscotch
  20. 12种 vo2dto 方法,就 BeanUtils.copyProperties 压测最拉胯!【快双11了,别用错喽】

热门文章

  1. idea 调用c#接口_Dubbo 接口测试方法
  2. 五款救急的linux文件恢复软件,五款救急的Linux文件恢复软件
  3. java中unicode显示乱码_Java 已知Java系统编码是GBK,jtextarea从一编码为Unicode的文本中读取数据,出现乱码,怎么正常显示?...
  4. Altium Designer20原理图库放置引脚报错解决方案
  5. android xml怎么建立,androidXmlSerializer创建XML文件
  6. mtk android 5.1 logo,Android ROM DIY之MTK平台手机通用移植
  7. 关于mysql优化_关于MySQL优化的几点总结
  8. java nlpir_中科院NLPIR中文分词java版
  9. Spring操作Redis
  10. cmd中Redis的启动