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

题面

题面较长,这里就不贴了

分析

看到不能经过有积水的边,即不能经过边权小于一定值的边,我们想到了kruskal重构树。我们把边按海拔高度从大到小排序,然后建立一棵Kruskal重构树。

树上维护什么呢?我们除了在点上记录高度外,把最底层的点1~n的权值设为点i到1的最短路径长度,然后维护子树最小值。我们在Kruskal重构树上从v开始树上倍增,找到深度最浅的高度>=水位线的点x,这样x子树中的点都是开车可以到达的,而最小步行距离就是x子树中的点对应到原图上后,到点1的距离。

代码

//https://www.luogu.org/problem/P4768
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define maxn 200000
#define maxm 400000
#define maxlogn 23
using namespace std;
typedef long long ll;
int t;
int n,m,q,k,s;
struct graph {
struct edge {
int from;
int to;
int next;
int len;
int height;
friend bool operator < (edge p,edge q){
return p.height>q.height;
}
}E[maxm*2+5];
int sz=1;
int head[maxn*2+5];
void clear(){
memset(head,0,sizeof(head));
sz=1;
}
void add_edge(int u,int v,int l,int h){
sz++;
E[sz].from=u;
E[sz].to=v;
E[sz].next=head[u];
E[sz].len=l;
E[sz].height=h;
head[u]=sz;
sz++;
E[sz].from=v;
E[sz].to=u;
E[sz].next=head[v];
E[sz].len=l;
E[sz].height=h;
head[v]=sz;
}
}G; struct tree{
struct edge{
int from;
int to;
int next;
}E[(maxn+maxn)*2+5];
int head[maxn+maxn+5];
int sz=1;
void clear(){
memset(head,0,sizeof(head));
sz=1;
}
void add_edge(int u,int v){
sz++;
E[sz].from=u;
E[sz].to=v;
E[sz].next=head[u];
head[u]=sz;
sz++;
E[sz].from=v;
E[sz].to=u;
E[sz].next=head[v];
head[v]=sz;
}
}T; struct heap_node{
ll dist;
int id;
heap_node(){ }
heap_node(int _id,ll _dist){
id=_id;
dist=_dist;
}
friend bool operator < (heap_node p,heap_node q){
return p.dist>q.dist;
}
};
int vis[maxn+5];
ll dist[maxn+5];
void dijkstra(int s){
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
dist[s]=0;
priority_queue<heap_node>q;
q.push(heap_node(s,0));
while(!q.empty()){
int x=q.top().id;
q.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=G.head[x];i;i=G.E[i].next){
int y=G.E[i].to;
if(dist[y]>dist[x]+G.E[i].len){
dist[y]=dist[x]+G.E[i].len;
q.push(heap_node(y,dist[y]));
}
}
}
} int newn=0;
int fa[maxn*2+5];
int find(int x){
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
} int log2n;
int hi[maxn*2+5];
ll dmin[maxn*2+5];
int deep[maxn*2+5];
int anc[maxn*2+5][maxlogn+5];
void dfs(int x,int fa){
deep[x]=deep[fa]+1;
anc[x][0]=fa;
for(int i=1;i<=log2n;i++) anc[x][i]=anc[anc[x][i-1]][i-1];
for(int i=T.head[x];i;i=T.E[i].next){
int y=T.E[i].to;
if(y!=fa){
dfs(y,x);
dmin[x]=min(dmin[x],dmin[y]);
}
}
}
ll query(int x,int lim){
for(int i=log2n;i>=0;i--){
if(anc[x][i]!=0&&hi[anc[x][i]]>lim){
x=anc[x][i];
}
}
return dmin[x];
}
void kruskal(){//建出kruskal重构树
newn=n;
for(int i=1;i<=n*2;i++) fa[i]=i;
sort(G.E+2,G.E+1+G.sz);
for(int i=2;i<=G.sz;i++){
int x=G.E[i].from;
int y=G.E[i].to;
int fx=find(x);
int fy=find(y);
if(fx!=fy){
newn++;
T.add_edge(fx,newn);
T.add_edge(fy,newn);
fa[fx]=newn;
fa[fy]=newn;
hi[newn]=G.E[i].height;
}
}
log2n=log2(newn);
memset(dmin,0x3f,sizeof(dmin));
for(int i=1;i<=n;i++) dmin[i]=dist[i];
dfs(newn,0);
} void ini(){
T.clear();
G.clear();
memset(anc,0,sizeof(anc));
memset(deep,0,sizeof(deep));
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
memset(dmin,0x3f,sizeof(dmin));
} int main() {
freopen("return.in","r",stdin);
freopen("return.out","w",stdout);
int u,v,l,a;
ll v0,p0;
ll lastans;
scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&m);
lastans=0;
ini();
for(int i=1;i<=m;i++){
scanf("%d %d %d %d",&u,&v,&l,&a);
G.add_edge(u,v,l,a);
}
dijkstra(1);
kruskal();
scanf("%d %d %d",&q,&k,&s);
for(int i=1;i<=q;i++){
scanf("%lld",&v0);
v0=(v0+k*lastans-1)%n+1;
scanf("%lld",&p0);
p0=(p0+k*lastans)%(s+1);
lastans=query(v0,p0);
printf("%lld\n",lastans);
}
}
}

[luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树)的更多相关文章

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

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

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

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

  3. NOI2018归程(Kruskal重构树)

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

  4. NOI2018d1t1 归程 (dijkstra+kruskal重构树)

    题意:给一张无向联通图,每条边有长度和高度,每次询问在高度大于p的边,从v点能到达的所有点到1号点的最短距离(强制在线) 首先dijkstra求出每个点到1号点的距离 易知:如果我按高度从高到低给边排 ...

  5. LOJ #2718. 「NOI2018」归程(Dijkstra + Kruskal重构树 + 倍增)

    题意 给你一个无向图,其中每条边有两个值 \(l, a\) 代表一条边的长度和海拔. 其中有 \(q\) 次询问(强制在线),每次询问给你两个参数 \(v, p\) ,表示在 \(v\) 出发,能开车 ...

  6. NOI2018 D1T1 洛谷P4768 归程 (Kruskal重构树)

    实际上是一个最短路问题,但加上了海拔这个条件限制,要在海拔<水位线p中找最短路. 这里使用Kruskal重构树,将其按海拔建成小根堆,我们就可以在树中用倍增找出他不得不下车的点:树中节点有两个权 ...

  7. 「NOI 2018」归程「Kruskal 重构树」

    题解 Kruskal重构树:每次一条边连接两个集合,建一个新点,点权为该边边权:把这两个集合的根连向新点. 性质:(如果求的是最大生成树)叶子结点是图中实际结点:叶子到根路径上点权递减:两点间lca的 ...

  8. 【BZOJ5415&UOJ393】归程(Kruskal重构树,最短路)

    题意:From https://www.cnblogs.com/Memory-of-winter/p/11628351.html 思路:先从1开始跑一遍dijkstra,建出kruskal重构树之后每 ...

  9. 【NOI 2018】归程(Kruskal重构树)

    题面在这里就不放了. 同步赛在做这个题的时候,心里有点纠结,很容易想到离线的做法,将边和询问一起按水位线排序,模拟水位下降,维护当前的各个联通块中距离$1$最近的距离,每次遇到询问时输出所在联通块的信 ...

随机推荐

  1. 什么是UAT

    基本概念 UAT,英文User Acceptance Test的简写,也就是用户验收测试,或用户可接受测试,系统开发生命周期方法论的一个阶段,这时相关的用户或独立测试人员根据测试计划和结果对系统进行测 ...

  2. 【BZOJ3601】一个人的数论

    题目链接 题意简述 求小于 n 且与 n 互质的数的 k 次方之和. Sol 要求的东西: \[\sum_{i=1}^n i^k [gcd(i,n)=1]\] 枚举 gcd 上个莫比乌斯函数: \[\ ...

  3. MySQL数据库4Python操作mysql、索引、慢查询日志

    目录 一.Python 操作 mysql 1.1python 操作 mysql 1.2查询数据 1.3增加(添加.更新)数据 1.4修改数据 1.5删除数据 1.6SQL注入问题 1.6.1问题的引入 ...

  4. 【GDOI2014模拟】雨天的尾巴

    题目 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连 根拔起,以及田地里 ...

  5. Comet OJ - Contest #6 C 一道树题 数学 + 推导

    Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) ...

  6. 【MySQL】 知识点记录

    0. 定位和排查问题的常用语句 查询 正在执行的事务(这个输出有事物状态表明是否等待锁):SELECT * FROM information_schema.INNODB_TRX 查看正在锁的事务:SE ...

  7. CTO爆料:2019程序员最需要了解的行业前沿技术是什么?

    安森,个推CTO 毕业于浙江大学,现全面负责个推技术选型.研发创新.运维管理等工作,已带领团队开发出针对移动互联网.金融风控等行业的多项前沿数据智能解决方案. 曾任MSN中国首席架构师,拥有十余年资深 ...

  8. docker 在centos上的安装实践

    使用yum安装docker yum -y install docker-io [root@localhost goblin]# yum -y install docker-io Loaded plug ...

  9. progress组件(进度条)

    progress组件:进度条 progress组件的属性: percent:类型:number 设置百分比 (0~100) show-info:类型:布尔 在进度条右侧显示百分比 border-rad ...

  10. Redis 简介,安装,卸载

    一.Redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(s ...