luogu 4768
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 + , oo = 1e9 + ; struct Node {
int u, v, len, high, nxt;
} E[N], G[N << ], Edge[N << ];
struct Node_ {
int u, dis_;
inline bool operator < (const Node_ a) const {return dis_ > a.dis_;}
}; int head_1[N], head_2[N << ], now;
int dis[N << ];
bool vis[N];
int fa[N << ];
int n, m;
int High[N << ];
int f[N << ][];
int deep[N << ]; #define gc getchar()
inline int read() {
int x = ;
char c = gc;
while(c < '' || c > '') c = gc;
while(c >= '' && c <= '') x = x * + c - '', 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][] = u, Dfs(G[i].v, u);}
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;}
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 = ; i <= ; i ++) for(int j = ; j <= (n * - ); j ++) f[j][i] = f[f[j][i - ]][i - ];} inline void Dijkstra() {
for(int i = ; i <= n; i ++) dis[i] = oo;
for(int i = ; i <= n; i ++) vis[i] = ;
priority_queue <Node_> Q;
Q.push((Node_) {, });
dis[] = ;
while(!Q.empty()) {
Node_ topp = Q.top();
Q.pop();
if(vis[topp.u]) continue;
vis[topp.u] = ;
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 + , E + m + , Cmp);
for(int i = ; i <= (n << ); i ++) fa[i] = i;
for(int i = ; i <= (n << ); i ++) head_2[i] = -;
int cnt = n;
now = ;
for(int i = ; i <= m; i ++) {
if(cnt == n * - ) 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, , sizeof f);
n = read(), m = read(); now = ;
for(int i = ; i <= n; i ++) head_1[i] = -;
for(int i = ; 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( * n - , ), Pre();
int Q = read(), K = read(), S = read(), Lastans = ;
for(; Q; Q --) {
int X = (read() + K * Lastans - ) % n + , H = (read() + K * Lastans) % (S + );
Lastans = dis[Jump(X, H)]; cout << Lastans << "\n";
}
}
return ;
}
luogu 4768的更多相关文章
- Luogu 4768 [NOI2018]归程
并不会写Kruskal重构树,两个$log$跑得比较卡. 首先考虑一下没有强制在线的要求怎么办,有一个比较容易想到的做法就是先跑一遍最短路,然后把所有边按照海拔从大到小排序,把所有询问的海拔也从大到小 ...
- Luogu 魔法学院杯-第二弹(萌新的第一法blog)
虽然有点久远 还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题 沉迷游戏,伤感情 #include <queue> ...
- luogu p1268 树的重量——构造,真正考验编程能力
题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...
- [luogu P2170] 选学霸(并查集+dp)
题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一 ...
- [luogu P2647] 最大收益(贪心+dp)
题目传送门:https://www.luogu.org/problem/show?pid=2647 题目描述 现在你面前有n个物品,编号分别为1,2,3,--,n.你可以在这当中任意选择任意多个物品. ...
- HDU 4768 Flyer(二分法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4768 题目大意:每组数据有n行输入,每行有三个数A.B.C,A<=B且小于2^32,从A到B每隔 ...
- Codevs 4768 跳石头 NOIP2015 DAY2 T1
4768 跳石头 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 传送门 题目描述 Description 一年一度的"跳石头"比赛又要开始了! ...
- Luogu 考前模拟Round. 1
A.情书 题目:http://www.luogu.org/problem/show?pid=2264 赛中:sb题,直接暴力匹配就行了,注意一下读入和最后一句话的分句 赛后:卧槽 怎么只有40 B.小 ...
- luogu P2580 于是他错误的点名开始了
luogu P2580 于是他错误的点名开始了 https://www.luogu.org/problem/show?pid=2580 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边 ...
随机推荐
- DMA存储器到存储器传输代码讲解
M to M:Flash to Sram,把内部flash的数据传输到内部SRAM(DRAM主要存放的是变量, flash 主要存放代码) M to P: SRAM to 串口,同时LED闪烁,演示D ...
- vmstat命令详解--转载
一.前言 vmstat命令: 用来获得有关进程.虚存.页面交换空间及 CPU活动的信息.这些信息反映了系统的负载情况 二.虚拟内存运行原理 在系统中运行的每个进程都需要使用到内存,但不是每个进程都需 ...
- 复杂链表的复制——牛客offer
题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head.(注意,输出结果中请不要返回参数中的节点引用, ...
- Unity塔防游戏的创建
看了下塔防游戏的教程,比我想像的还简单一些,有些收获: (1)敌人的移动路径,其时比较简单,用了N个Empty GameObject作为路径点,然后做一个总的Empty GameObject 作为父级 ...
- 整理一下rmq
rmq(int i,int j,int a)表示查询a数组i到j区间的内容中的最大/最小值核心部分为二分区间以及st预处理算法 先说st预处理算法吧 int dp[i][j];//表示以i开始 长度为 ...
- (十五)struts2之注解
一.作用 以用来替换struts.xml配置文件 使用前提 :必须引入struts2-convention-plugin-2.3.14.jar 这个jar包 二.参数 @Action来代替<ac ...
- Navicat远程连接centos上mysql出错
原因1:mysql账户是不允许远程连接 参考:centos安装mysql(for 小白) 打开远程连接 原因2:3306端口未开启 开启端口:iptables -I INPUT -p tcp --dp ...
- 同步/异步/阻塞/非阻塞/BIO/NIO/AIO
转摘自:https://www.cnblogs.com/lixinjie/p/a-post-about-io-clearly.html 常规的误区 假设有一个展示用户详情的需求,分两步,先调用一个HT ...
- K2 BPM_万翼科技携手上海斯歌,全面启动K2平台升级项目_十年专注业务流程管理系统
2019年7月25日,万翼科技和上海斯歌在深圳召开了“2019年K2平台升级项目启动会”.万翼科技核心合伙人何建春.管金华,协同管理支撑组负责人贾磊,K2平台产品负责人黄平显,上海斯歌总裁李明,技术研 ...
- macOS 在终端中使用 adb命令,每次都要source ~/.bash_profile 才生效
macOS下已经配置好Android开发环境,环境变量也添加了,但是在终端中使用adb命令每次都需要source .bash_profile之后才能识别, 否则就提示 zsh: command no ...