NOI2018 D1T1 洛谷P4768 归程 (Kruskal重构树)
实际上是一个最短路问题,但加上了海拔这个条件限制,要在海拔<水位线p中找最短路。
这里使用Kruskal重构树,将其按海拔建成小根堆,我们就可以在树中用倍增找出他不得不下车的点;树中节点有两个权值L(最短路)和a(海拔),找到我们想要的a,此时的L就是答案。
来看一下总的算法分析吧......
先按海拔a从高到低排序,然后构建Kruskal重构树,按海拔每次选出剩余边中海拔最高的一条边插入到树中,建成一个小根堆。
接下来考虑询问——
对于一个水位线p:
(1)树中点x的海拔大于p,那么在x的子树中,不需要下车(因为是个小根堆嘛),对答案没有贡献。
(2)我们找到了x节点的海拔小于p,那么他就要在x点下车,对答案的贡献就是x到1的距离,两个子问题:用dijkstra预处理1到各点的最短路;用倍增找到x节点。
1 #include<bits/stdc++.h>
2 using namespace std;
3 #define INF 0x3f3f3f3f
4 inline int read(){
5 int x=0;
6 char ch=getchar();
7 while(ch<'0'||ch>'9') ch=getchar();
8 while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
9 return x;
10 }
11 const int N=4e5+10;
12 int fa[N][20],dep[N];
13 int T,n,m,last;
14 struct node{
15 int u,v,l,a,nxt;
16 bool operator<(const node &b) const{return a>b.a;} //小根堆
17 }e[N<<1],tmp[N<<1],edge[N<<1];
18 int head[N],tot,dis[N];
19 struct heap{
20 int x,dis;
21 bool operator<(const heap&b) const {return dis>b.dis;}//小根堆
22 };
23 int f[N],cnt;
24
25 inline void Add(int x,int y,int z){
26 edge[++tot].v=y,edge[tot].l=z,edge[tot].nxt=head[x];
27 head[x]=tot;
28 }
29
30 inline int find(int x){
31 return f[x]==x?x:f[x]=find(f[x]);
32 }
33
34 inline void add(int x,int y){
35 edge[++tot].v=y,edge[tot].nxt=head[x];
36 head[x]=tot;
37 }
38
39 inline void init(){
40 memset(head,0,sizeof(head));
41 memset(fa,0,sizeof(fa));
42 memset(f,0,sizeof(f));
43 memset(tmp,0,sizeof(tmp));
44 memset(edge,0,sizeof(edge));
45 last=tot=0;
46 }
47
48 inline void dijkstra(){//求出从1到各点的最短路
49 priority_queue<heap> q;
50 memset(dis,0x3f,sizeof(dis));
51 dis[1]=0;
52 q.push((heap){1,0});
53 while(!q.empty()){
54 heap now=q.top();
55 q.pop();
56 int x=now.x;
57 if(dis[x]<now.dis) continue;//剪枝
58 for(int i=head[x];i;i=edge[i].nxt){
59 int y=edge[i].v;
60 if(dis[y]>dis[x]+edge[i].l){
61 dis[y]=dis[x]+edge[i].l;
62 q.push((heap){y,dis[y]});
63 }
64 }
65 }
66 }
67
68 inline void kruskal(){
69 sort(e+1,e+m+1);
70 for(int i=1;i<=n;i++) f[i]=i;
71 cnt=n;
72 int num=0;//统计边数
73 for(int i=1;i<=m;i++){
74 int fu=find(e[i].u),fv=find(e[i].v);
75 if(fu!=fv){
76 num++;
77 tmp[++cnt].a=e[i].a;//海拔
78 f[fu]=f[fv]=f[cnt]=cnt;
79 add(cnt,fu),add(cnt,fv);//父亲向孩子连边
80 }
81 if(num==n-1) break;
82 }
83 }
84
85 inline void dfs(int x,int p){
86 dep[x]=dep[p]+1,fa[x][0]=p;
87 for(int i=1;i<=19;i++)//dfs过程中处理ST
88 fa[x][i]=fa[fa[x][i-1]][i-1];
89 for(int i=head[x];i;i=edge[i].nxt){
90 int y=edge[i].v;
91 dfs(y,x);
92 tmp[x].l=min(tmp[x].l,tmp[y].l);//最短路
93 }
94 }
95
96 inline int query(int x,int y){//从x出发往上跳,找到海拔大于y的最小的点
97 for(int i=19;i>=0;i--){
98 if(dep[x]-(1<<i)>0&&tmp[fa[x][i]].a>y)
99 x=fa[x][i];
100 }
101 return tmp[x].l;//答案就是该点的权值
102 }
103
104 inline void solve(){
105 kruskal();
106 dfs(cnt,0);//从树根开始
107 int q=read(),k=read(),s=read();
108 while(q--){
109 int x=(k*last+read()-1)%n+1,y=(k*last+read())%(s+1);
110 printf("%d\n",last=query(x,y));
111 }
112 }
113
114 int main(){
115 T=read();
116 while(T--){
117 init();//初始化
118 n=read(),m=read();
119 for(int i=1;i<=m;i++){
120 e[i].u=read(),e[i].v=read(),e[i].l=read(),e[i].a=read();
121 Add(e[i].u,e[i].v,e[i].l),Add(e[i].v,e[i].u,e[i].l);//建图
122 }
123 dijkstra();
124 for(int i=1;i<=n;i++) tmp[i].l=dis[i];//重构树上叶子节点的权值为该点到1的最短路
125 for(int i=n+1;i<=2*n;i++) tmp[i].l=INF;
126 memset(head,0,sizeof(head)),tot=0;
127 solve();
128 }
129 }
NOI2018 D1T1 洛谷P4768 归程 (Kruskal重构树)的更多相关文章
- 洛谷P4197 Peaks(Kruskal重构树 主席树)
题意 题目链接 往后中文题就不翻译了qwq Sol 又是码农题..出题人这是强行把Kruskal重构树和主席树拼一块了啊.. 首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的 ...
- NOI Day1T1归程(Kruskal重构树+Dijkstra)
NOI Day1T1归程(Kruskal重构树+Dijkstra) 题目 洛谷题目传送门 题解 其实我不想写......,所以...... 挖个坑......我以后一定会补的 luogu的题解讲的还是 ...
- [洛谷P4768] [NOI2018]归程 (kruskal重构树模板讲解)
洛谷题目链接:[NOI2018]归程 因为题面复制过来有点炸格式,所以要看题目就点一下链接吧\(qwq\) 题意: 在一张无向图上,每一条边都有一个长度和海拔高度,小\(Y\)的家在\(1\)节点,并 ...
- 洛谷P4768 [NOI2018]归程(Kruskal重构树)
题意 直接看题目吧,不好描述 Sol 考虑暴力做法 首先预处理出从$1$到每个节点的最短路, 对于每次询问,暴力的从这个点BFS,从能走到的点里面取$min$ 考虑如何优化,这里要用到Kruskal重 ...
- LOJ.2718.[NOI2018]归程(Kruskal重构树 倍增)
LOJ2718 BZOJ5415 洛谷P4768 Rank3+Rank1无压力 BZOJ最初还不是一道权限题... Update 2019.1.5 UOJ上被hack了....好像是纯一条链的数据过不 ...
- [NOI2018]归程 kruskal重构树
[NOI2018]归程 LG传送门 kruskal重构树模板题. 另一篇文章里有关于kruskal重构树更详细的介绍和更板子的题目. 题意懒得说了,这题的关键在于快速找出从查询的点出发能到达的点(即经 ...
- BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra
题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l,a 描述一条边的长度.海 ...
- BZOJ 5415: [Noi2018]归程(kruskal重构树)
解题思路 \(NOI2018\)的\(Day1\) \(T1\),当时打网络赛的时候不会做.学了一下\(kruskal\)重构树后发现问题迎刃而解了.根据\(kruskal\)的性质,如果要找从\(u ...
- #2718. 「NOI2018」归程 kruskal重构树
链接 https://loj.ac/problem/2718 思路 我们希望x所在的连通块尽量的大,而且尽量走高处 离线的话可以询问排序,kruskal过程中更新答案 在线就要用kruskal重构树 ...
随机推荐
- 先导,对IOC容器的理解
先导,对IOC容器的理解 通俗的讲就是把你的class类交给spring的IOC容器去管理 需要对该类的属性注入一些值,就可以通过spring提供的xml文件或者注解进行注入 自己使用时在IOC容器工 ...
- LuoguP2575 高手过招(博弈论)
空格数变吗?不变呀 阶梯博弈阶梯数变吗?不变呀 那这不就阶梯博弈,每行一栋楼,爬完\(mex\)就可以了吗? #include <iostream> #include <cstdio ...
- ArkUI block 标签
block 标签在构建时不会被当作真实 DOM,而 block 标签之下的标签都会被渲染到真实 DOM 中.它类似于 Vue 的 template 标签. <div class="co ...
- xray+awvs的联动
前言:xray是一款强大的漏扫工具,配合awvs的爬站功能可以十分轻松实现全自动挖洞,这里awvs我是使用的是12版本 1.启动xray,监听本地指定端口,这里我监听的是2222端口 命令:xray_ ...
- [CF1500E] Subset Trick (平衡树)
题面 洛谷翻译 V a n y a \rm Vanya Vanya 有一个初始大小为 n n n 的集合 S S S 和 q q q 次往集合加数/删数的操作.(集合中每个数字不同) 称一个数 x x ...
- (四连测)滑雪场的高度差题解---二分 + 搜索---DD(XYX)的博客
滑雪场的高度差 时间限制: 1 Sec 内存限制: 128 MB 题目描述 滑雪场可以看成M x N的网格状山地(1 <= M,N <= 500),每个网格是一个近似的平面,具有水平高度 ...
- 【java】学习路线9-非静态内部类、外部类
//内部类只能在其外部类当中使用//局部内部类:定义在方法里面//如果内部类和外部类有重名,就近原则在内部类中优先访问内部类.//如果想访问宿主类的同名成员,使用OuterClass.this.xxx ...
- 「题解报告」P7301 【[USACO21JAN] Spaced Out S】
原题传送门 神奇的5分算法:直接输出样例. 20分算法 直接把每个点是否有牛的状态DFS一遍同时判断是否合法,时间复杂度约为\(O(2^{n^2})\)(因为有判断合法的剪枝所以会比这个低).而在前四 ...
- 在Linux下配置RealVNC和TigerVNC
作者:alittlemc | 更新中 | 原创文章,可能有技术理解错误,欢迎指正,请与我联系,谢谢! 命令和快速总结 realvnc创建# :会话id -name 取名字 -depth 色深 -geo ...
- 记录一次数据库CPU被打满的排查过程
1 前言 近期随着数据量的增长,数据库CPU使用率100%报警频繁起来.第一个想到的就是慢Sql,我们对未合理运用索引的表加入索引后,问题依然没有得到解决,深入排查时,发现在 order by id ...