NOI2018d1t1 归程 (dijkstra+kruskal重构树)
题意:给一张无向联通图,每条边有长度和高度,每次询问在高度大于p的边,从v点能到达的所有点到1号点的最短距离(强制在线)
首先dijkstra求出每个点到1号点的距离
易知:如果我按高度从高到低给边排序然后用kruskal的方法做出一棵生成树,那么在高度大于p的条件下,在原图中联通的两点在生成树中依旧联通
于是就可以在做kruskal的时候建一个叫做重构树的东西,在用并查集维护联通块的同时维护一个树结构:
对于每条边,若原本两端点u,v不连通,则新建一个节点t,设a,b为u,v在并查集中的祖先,令并查集和树结构中fa[a]=fa[b]=t,同时记下树中t的两个孩子为a,b,以及t的高度与边的高度相同
这样,树中的每棵子树的叶节点都是连通的,并且树中深度越深,节点对应边的高度就越大
dfs一下就可以处理出每个子树对应联通块的距1号点的最近距离。
然后对于点v,就可以倍增找出高度恰大于p的那个节点,就是最后结果
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define LL long long int
#define pa pair<int,int>
using namespace std;
const int maxn=2e5+,logn=,maxm=4e5+,inf=0x3f3f3f3f; int rd(){
int x=;char c=getchar();
while(c<''||c>'') c=getchar();
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x;
} struct Edge{
int a,b,l,h,ne;
}eg[maxm*];
struct Node{
int fa[logn],v,h,ch[];
}tr[maxn*];
int bcj[maxn*],tct;
int N,M,Q,K,S;
int egh[maxn],ect;
int dis[maxn];
priority_queue<pa,vector<pa>,greater<pa> > q; inline void adeg(int a,int b,int l,int h){
eg[ect].a=a;eg[ect].b=b;eg[ect].l=l;eg[ect].h=h;eg[ect].ne=egh[a];egh[a]=ect++;
} void dijkstra(){
memset(dis,,sizeof(dis));dis[]=;
q.push(make_pair(,));
while(!q.empty()){
int p=q.top().second;q.pop();
for(int i=egh[p];i!=-;i=eg[i].ne){
int b=eg[i].b;
if(dis[b]>dis[p]+eg[i].l){
dis[b]=dis[p]+eg[i].l;
q.push(make_pair(dis[b],b));
}
}
}
} int getf(int x){return x==bcj[x]?x:bcj[x]=getf(bcj[x]);} void kruskal(){
memset(tr,,sizeof(tr));
for(int i=;i<=N*;i++) bcj[i]=i,tr[i].v=inf;tct=N;
for(int i=,n=;i<ect&&n<N;i++){
int a=getf(eg[i].a),b=getf(eg[i].b);
if(a==b) continue;
bcj[a]=bcj[b]=++tct;
tr[a].fa[]=tr[b].fa[]=tct;
tr[tct].ch[]=a;tr[tct].ch[]=b;
tr[tct].h=eg[i].h;n++;
}
} void dfs(int x){
for(int i=;i<logn-;i++){
if(!tr[tr[x].fa[i]].fa[i]) break;
tr[x].fa[i+]=tr[tr[x].fa[i]].fa[i];
}
if(tr[x].ch[]){
dfs(tr[x].ch[]);dfs(tr[x].ch[]);
tr[x].v=min(tr[tr[x].ch[]].v,tr[tr[x].ch[]].v);
}else tr[x].v=dis[x];
} inline bool cmp(Edge a,Edge b){
return a.h>b.h;
} int query(int v,int p){
for(int i=logn-;i>=;i--){
if(tr[v].fa[i]&&tr[tr[v].fa[i]].h>p) v=tr[v].fa[i];
}return tr[v].v;
} int main(){
int i,j,k;
//freopen("return.in","r",stdin);
for(int T=rd();T;T--){
N=rd(),M=rd();memset(egh,-,sizeof(egh));ect=;
for(i=;i<=M;i++){
int a=rd(),b=rd(),c=rd(),d=rd();
adeg(a,b,c,d);adeg(b,a,c,d);
}dijkstra();
sort(eg,eg+ect,cmp);kruskal();dfs(tct);
Q=rd(),K=rd(),S=rd();
int lastans=;
for(i=;i<=Q;i++){
int v=(rd()+K*lastans-)%N+;
int p=(rd()+K*lastans)%(S+);
printf("%d\n",lastans=query(v,p));
}
}
}
NOI2018d1t1 归程 (dijkstra+kruskal重构树)的更多相关文章
- [luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树)
[luogu4768] [NOI2018] 归程 (Dijkstra+Kruskal重构树) 题面 题面较长,这里就不贴了 分析 看到不能经过有积水的边,即不能经过边权小于一定值的边,我们想到了kru ...
- Luogu P4768 [NOI2018]归程(Dijkstra+Kruskal重构树)
P4768 [NOI2018]归程 题面 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 \(n\) 个节点. \(m\) 条边的无向连通图(节点的编 ...
- LOJ #2718. 「NOI2018」归程(Dijkstra + Kruskal重构树 + 倍增)
题意 给你一个无向图,其中每条边有两个值 \(l, a\) 代表一条边的长度和海拔. 其中有 \(q\) 次询问(强制在线),每次询问给你两个参数 \(v, p\) ,表示在 \(v\) 出发,能开车 ...
- P4768 [NOI2018]归程(kruskal 重构树)
洛谷P4768 [NOI2018]归程 LOJ#2718.「NOI2018」归程 用到 kruskal 重构树,所以先说这是个啥 显然,这和 kruskal 算法有关系 (废话 这个重构树是一个有点权 ...
- NOI2018归程(Kruskal重构树)
题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n). 我们依次用 l,a 描述一条边的长度. ...
- 「NOI 2018」归程「Kruskal 重构树」
题解 Kruskal重构树:每次一条边连接两个集合,建一个新点,点权为该边边权:把这两个集合的根连向新点. 性质:(如果求的是最大生成树)叶子结点是图中实际结点:叶子到根路径上点权递减:两点间lca的 ...
- 【BZOJ5415&UOJ393】归程(Kruskal重构树,最短路)
题意:From https://www.cnblogs.com/Memory-of-winter/p/11628351.html 思路:先从1开始跑一遍dijkstra,建出kruskal重构树之后每 ...
- NOI2018 D1T1 洛谷P4768 归程 (Kruskal重构树)
实际上是一个最短路问题,但加上了海拔这个条件限制,要在海拔<水位线p中找最短路. 这里使用Kruskal重构树,将其按海拔建成小根堆,我们就可以在树中用倍增找出他不得不下车的点:树中节点有两个权 ...
- 【NOI 2018】归程(Kruskal重构树)
题面在这里就不放了. 同步赛在做这个题的时候,心里有点纠结,很容易想到离线的做法,将边和询问一起按水位线排序,模拟水位下降,维护当前的各个联通块中距离$1$最近的距离,每次遇到询问时输出所在联通块的信 ...
随机推荐
- semantic-ui 分段
分段:用于创建一组相关联的内容. 1.创建一个基础的分段 在class中加一个segment的class即可 <div class="ui segment"> < ...
- http/https与websocket的ws/wss的关系以及通过Nginx的配置
http/https与websocket的ws/wss的关系 - 哒哒哒 - CSDN博客 https://blog.csdn.net/Garrettzxd/article/details/81674 ...
- html问题汇总
1.textarea换行 textarea中无法使用<br/>换行,需要使用\n 2.textarea无法提交 我们知道表单中的元素需要设置name属性才能够提交,但是如果设置了disab ...
- 对B+树,B树,红黑树的理解
出处:https://www.jianshu.com/p/86a1fd2d7406 写在前面,好像不同的教材对b树,b-树的定义不一样.我就不纠结这个到底是叫b-树还是b-树了. 如图所示,区别有以下 ...
- JS对象、基本类型和字面量的区别
字面值: var str1='this is a simple string'; var num1=1.45; var answer1=true; 基本类型: var str2=String('thi ...
- hadoop第一个例子
Java.io.URL 1.编写java程序 package com.company; import java.io.IOException; import java.io.InputStream; ...
- python之路-字符串
一.类型转换 a = 10 print(type(a)) # <class 'int'> d = str(a) # 把数字转换成str print(type(d)) # <class ...
- Prism框架研究(一)
从今天起开始写一个Prism框架的学习博客,今天是第一篇,所以从最基本的一些概念开始学习这个基于MVVM的框架的学习,首先看一下Prism代表什么,这里引用一下比较官方的英文解释来看一下:Prism ...
- Java的HashMap数据结构
标题太大~~~自己做点笔记.别人写得太好了. https://www.cnblogs.com/liwei2222/p/8013367.html HashMap 1.6时代, 使用Entry[]数组, ...
- delphi中 dataset容易出错的地方
最近写delphi项目,用到的数据集中的dataset,一直修改exception啊,写下过程. 在对数据集进行任何操作之前,首先要打开数据集.要打开数据集,可以把Active属性设为True,例如: ...