今年D1T1,平心而论,如果能想到kruskal重构树还是很简单的。

......苟屁啊!虽然跟其他的比是简单些,但是思维难度中上,代码难度中上,怎么看都很符合NOI T1啊。

本题还有可持久化并查集的做法,以高度为版本。我没有打......

言归正传,来看题。

给你一个无向图,每条边有高度和长度。每次询问,从点s出发,只能经过高度大于h的边所能到达的点中,距1号点最近的点的距离。强制在线。

n<=200000,m<=400000,q<=400000

首先,离线有65分,十分可观。我们把边和询问都按照高度排序。然后依次加入,并查集维护连通块内dis最小值。

克鲁斯卡尔重构树解法:

首先讲什么是克鲁斯卡尔重构树:说起来也蛮简单,就是你把边排序,加边的时候如果连通就不加,否则新建节点代表这个连通块,边的两端所在连通块的代表节点作为这个新节点的两个子节点。

这样你要查询高度h时dis min,只需维护一个节点所代表连通块内dis最小值即可。每次向上跳,可以发现一条链上的dis min单调不增。然后就倍增了,类似lca。

啊我到底在口胡什么。

 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue> const int N = , INF = 0x7f7f7f7f; struct Edge_1 {
int v, len, nex;
}edge_1[N << ]; int top_1; // for dijkstra struct POI {
int id, dis;
inline bool operator <(const POI &d) const {
return dis > d.dis;
}
POI(int a, int b) {
id = a;
dis = b;
}
}; // for dijkstra struct Edge_2 {
int u, v, h;
inline bool operator <(const Edge_2 &d) const {
return h > d.h;
}
}edge_2[N << ]; int top_2; // for sort kruskal struct UFS {
int fa[N * ];
inline void clear() {
for(int i = ; i < N * ; i++) {
fa[i] = i;
}
return;
}
UFS() {
clear();
}
int find(int x) {
if(fa[x] == x) {
return x;
}
return fa[x] = find(fa[x]);
}
inline void merge(int x, int y) { // x <- y
fa[find(y)] = find(x);
return;
}
}ufs; int e[N], dis[N * ]; // for dijkstra
int fa[N * ][], tot, h[N * ]; // for kruskal inline void add_1(int x, int y, int z) {
top_1++;
edge_1[top_1].v = y;
edge_1[top_1].len = z;
edge_1[top_1].nex = e[x];
e[x] = top_1;
return;
} inline void add_2(int x, int y, int z) {
top_2++;
edge_2[top_2].u = x;
edge_2[top_2].v = y;
edge_2[top_2].h = z;
return;
} inline void clear() {
top_1 = ;
top_2 = ;
memset(e, , sizeof(e));
ufs.clear();
return;
} inline void dijkstra() {
std::priority_queue<POI> Q;
memset(dis, 0x3f, sizeof(dis));
dis[] = ;
Q.push(POI(, )); // POI(id, dis)
while(!Q.empty()) {
while(!Q.empty() && dis[Q.top().id] != Q.top().dis) {
Q.pop();
}
if(Q.empty()) {
break;
}
int x = Q.top().id;
Q.pop();
for(int i = e[x]; i; i = edge_1[i].nex) {
int y = edge_1[i].v;
if(dis[y] > dis[x] + edge_1[i].len) {
dis[y] = dis[x] + edge_1[i].len;
Q.push(POI(y, dis[y]));
}
}
}
return;
} inline void add(int p) {
int x = ufs.find(edge_2[p].u);
int y = ufs.find(edge_2[p].v);
if(x == y) {
return;
}
++tot;
fa[x][] = tot;
fa[y][] = tot;
ufs.merge(tot, x);
ufs.merge(tot, y);
h[tot] = edge_2[p].h;
dis[tot] = std::min(dis[x], dis[y]);
return;
} inline int solve(int x, int high) {
int t = ;
while(t >= ) {
if(h[fa[x][t]] > high) {
x = fa[x][t];
}
t--;
}
return dis[x];
} int main() {
int T;
scanf("%d", &T);
while(T--) {
int n, m;
scanf("%d%d", &n, &m);
tot = n;
h[] = -;
for(int i = , x, y, z, w; i <= m; i++) {
scanf("%d%d%d%d", &x, &y, &z, &w);
add_1(x, y, z);
add_1(y, x, z);
add_2(x, y, w);
} // prework
dijkstra();
std::sort(edge_2 + , edge_2 + m + );
for(int i = ; i <= m; i++) {
add(i);
}
for(int i = ; i <= ; i++) {
for(int x = ; x <= tot; x++) {
fa[x][i] = fa[fa[x][i - ]][i - ];
}
} int q, k, s, op, high, la = ;
scanf("%d%d%d", &q, &k, &s);
while(q--) {
scanf("%d%d", &op, &high);
op = (op + k * la - ) % n + ;
high = (high + k * la) % (s + );
la = solve(op, high);
printf("%d\n", la);
}
clear();
}
return ;
}

AC代码

170行代码还行。

[NOI2018]归程的更多相关文章

  1. [NOI2018]归程 kruskal重构树

    [NOI2018]归程 LG传送门 kruskal重构树模板题. 另一篇文章里有关于kruskal重构树更详细的介绍和更板子的题目. 题意懒得说了,这题的关键在于快速找出从查询的点出发能到达的点(即经 ...

  2. [洛谷P4768] [NOI2018]归程 (kruskal重构树模板讲解)

    洛谷题目链接:[NOI2018]归程 因为题面复制过来有点炸格式,所以要看题目就点一下链接吧\(qwq\) 题意: 在一张无向图上,每一条边都有一个长度和海拔高度,小\(Y\)的家在\(1\)节点,并 ...

  3. NOI2018 D1T1 [NOI2018]归程 解题报告

    P4768 [NOI2018]归程 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 \(n\) 个节点.\(m\) 条边的无向连通图(节点的编号从 \ ...

  4. BZOJ_5415_[Noi2018]归程_kruscal重构树+倍增+最短路

    BZOJ_5415_[Noi2018]归程_kruscal重构树+倍增 Description www.lydsy.com/JudgeOnline/upload/noi2018day1.pdf 好久不 ...

  5. 题解 NOI2018 归程

    题解 NOI2018 归程 题意 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l, ...

  6. [NOI2018]归程(kruscal重构树)

    [NOI2018]归程 题面太长辣,戳这里 模拟赛上写了一个spfa (关于spfa,它已经死了),然后一个st表水完暴力跑路.考后说是Kruscal重构树或者可持久化并查集???这都是些什么东西.不 ...

  7. [luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树)

    [luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树) 题面 题面较长,这里就不贴了 分析 看到不能经过有积水的边,即不能经过边权小于一定值的边,我们想到了kru ...

  8. Luogu P4768 [NOI2018]归程(Dijkstra+Kruskal重构树)

    P4768 [NOI2018]归程 题面 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 \(n\) 个节点. \(m\) 条边的无向连通图(节点的编 ...

  9. P4768 [NOI2018]归程(kruskal 重构树)

    洛谷P4768 [NOI2018]归程 LOJ#2718.「NOI2018」归程 用到 kruskal 重构树,所以先说这是个啥 显然,这和 kruskal 算法有关系 (废话 这个重构树是一个有点权 ...

  10. BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra

    题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l,a 描述一条边的长度.海 ...

随机推荐

  1. JavaMail入门第一篇 邮件简介及API概述

    现如今,电子邮件在我们的生活当中扮演着越来越重要的角色,我们每个人几乎都会与其打交道(至少时不时我们都会接收到莫名其妙的垃圾邮件),在工作中,使用邮件进行交流沟通,可以使我们的工作有迹可循,也显的较为 ...

  2. spring mvc常用注解总结

    1.@RequestMapping@RequestMappingRequestMapping是一个用来处理请求地址映射的注解(将请求映射到对应的控制器方法中),可用于类或方法上.用于类上,表示类中的所 ...

  3. 莫烦scikit-learn学习自修第一天【scikit-learn安装】

    1. 机器学习的分类 (1)有监督学习(包括分类和回归) (2)无监督学习(包括聚类) (3)强化学习 2. 安装 (1)安装python (2)安装numpy >=1.6.1 (3)安装sci ...

  4. DButils实现数据库表下划线转bean中驼峰格式

    准备: QueryRunner queryRunner = new QueryRunner();//开启下划线->驼峰转换所用BeanProcessor bean = new GenerousB ...

  5. 剖析插件 DataTable 自定义列表列get请求如何书写传递的参数

    重点代码Demo 已用 斜体标注 后端flask: @task_mgm.route('/taskinfo_editID=<int:num>', methods=['GET', 'POST' ...

  6. Python 第三方库 cp27、cp35 等文件名的含义(转)

    转自 https://blog.csdn.net/lanchunhui/article/details/62417519 转自 https://stackoverflow.com/questions/ ...

  7. Web API 2 使用Entity Framework Part 1.

    创建项目 打开Visual Studio,选择ASP.NET Web Application,项目名称BookService并点击OK. 选择Web API 模板 如果你想使用Azure App Se ...

  8. HDU 1074 Doing Homework(经典状压dp)

    题目链接  Doing Homework        Ignatius has just come back school from the 30th ACM/ICPC. Now he has a ...

  9. poj-2337(欧拉回路输出)

    题意:给你n个字符串,每个字符串可以和另一个字符串连接的前提是,前一个字符串的尾字符等于后一个字符串的首字符,问你存不存在欧拉通路并输出 解题思路:基本标准流程,建图:把一个字符串可以看作一条首字符指 ...

  10. Java拦截器

    拦截器,主要用于拦截前端请求,常用于登录检查. 下面是演示使用拦截器拦截未登录的用户访问需要登录的模块情景,使用配置方式实现和注解方式实现代码: 配置方式: 1.web.xml中配置监听器,对于所有的 ...