[NOI2018]归程
今年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]归程的更多相关文章
- [NOI2018]归程 kruskal重构树
[NOI2018]归程 LG传送门 kruskal重构树模板题. 另一篇文章里有关于kruskal重构树更详细的介绍和更板子的题目. 题意懒得说了,这题的关键在于快速找出从查询的点出发能到达的点(即经 ...
- [洛谷P4768] [NOI2018]归程 (kruskal重构树模板讲解)
洛谷题目链接:[NOI2018]归程 因为题面复制过来有点炸格式,所以要看题目就点一下链接吧\(qwq\) 题意: 在一张无向图上,每一条边都有一个长度和海拔高度,小\(Y\)的家在\(1\)节点,并 ...
- NOI2018 D1T1 [NOI2018]归程 解题报告
P4768 [NOI2018]归程 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 \(n\) 个节点.\(m\) 条边的无向连通图(节点的编号从 \ ...
- BZOJ_5415_[Noi2018]归程_kruscal重构树+倍增+最短路
BZOJ_5415_[Noi2018]归程_kruscal重构树+倍增 Description www.lydsy.com/JudgeOnline/upload/noi2018day1.pdf 好久不 ...
- 题解 NOI2018 归程
题解 NOI2018 归程 题意 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l, ...
- [NOI2018]归程(kruscal重构树)
[NOI2018]归程 题面太长辣,戳这里 模拟赛上写了一个spfa (关于spfa,它已经死了),然后一个st表水完暴力跑路.考后说是Kruscal重构树或者可持久化并查集???这都是些什么东西.不 ...
- [luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树)
[luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树) 题面 题面较长,这里就不贴了 分析 看到不能经过有积水的边,即不能经过边权小于一定值的边,我们想到了kru ...
- Luogu P4768 [NOI2018]归程(Dijkstra+Kruskal重构树)
P4768 [NOI2018]归程 题面 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 \(n\) 个节点. \(m\) 条边的无向连通图(节点的编 ...
- P4768 [NOI2018]归程(kruskal 重构树)
洛谷P4768 [NOI2018]归程 LOJ#2718.「NOI2018」归程 用到 kruskal 重构树,所以先说这是个啥 显然,这和 kruskal 算法有关系 (废话 这个重构树是一个有点权 ...
- BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra
题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l,a 描述一条边的长度.海 ...
随机推荐
- JavaMail入门第一篇 邮件简介及API概述
现如今,电子邮件在我们的生活当中扮演着越来越重要的角色,我们每个人几乎都会与其打交道(至少时不时我们都会接收到莫名其妙的垃圾邮件),在工作中,使用邮件进行交流沟通,可以使我们的工作有迹可循,也显的较为 ...
- spring mvc常用注解总结
1.@RequestMapping@RequestMappingRequestMapping是一个用来处理请求地址映射的注解(将请求映射到对应的控制器方法中),可用于类或方法上.用于类上,表示类中的所 ...
- 莫烦scikit-learn学习自修第一天【scikit-learn安装】
1. 机器学习的分类 (1)有监督学习(包括分类和回归) (2)无监督学习(包括聚类) (3)强化学习 2. 安装 (1)安装python (2)安装numpy >=1.6.1 (3)安装sci ...
- DButils实现数据库表下划线转bean中驼峰格式
准备: QueryRunner queryRunner = new QueryRunner();//开启下划线->驼峰转换所用BeanProcessor bean = new GenerousB ...
- 剖析插件 DataTable 自定义列表列get请求如何书写传递的参数
重点代码Demo 已用 斜体标注 后端flask: @task_mgm.route('/taskinfo_editID=<int:num>', methods=['GET', 'POST' ...
- Python 第三方库 cp27、cp35 等文件名的含义(转)
转自 https://blog.csdn.net/lanchunhui/article/details/62417519 转自 https://stackoverflow.com/questions/ ...
- Web API 2 使用Entity Framework Part 1.
创建项目 打开Visual Studio,选择ASP.NET Web Application,项目名称BookService并点击OK. 选择Web API 模板 如果你想使用Azure App Se ...
- HDU 1074 Doing Homework(经典状压dp)
题目链接 Doing Homework Ignatius has just come back school from the 30th ACM/ICPC. Now he has a ...
- poj-2337(欧拉回路输出)
题意:给你n个字符串,每个字符串可以和另一个字符串连接的前提是,前一个字符串的尾字符等于后一个字符串的首字符,问你存不存在欧拉通路并输出 解题思路:基本标准流程,建图:把一个字符串可以看作一条首字符指 ...
- Java拦截器
拦截器,主要用于拦截前端请求,常用于登录检查. 下面是演示使用拦截器拦截未登录的用户访问需要登录的模块情景,使用配置方式实现和注解方式实现代码: 配置方式: 1.web.xml中配置监听器,对于所有的 ...