题意:给一张无向联通图,每条边有长度和高度,每次询问在高度大于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重构树)的更多相关文章

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

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

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

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

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

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

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

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

  5. NOI2018归程(Kruskal重构树)

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

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

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

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

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

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

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

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

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

随机推荐

  1. node学习: package.json

    package.json 定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称.版本.许可证等元数据) 1.创建 package.json npm init npm init –yes 2.p ...

  2. [转帖]分布式Unique ID的生成方法一览

    分布式Unique ID的生成方法一览 http://www.importnew.com/22211.html 分布式的Unique ID的用途如此广泛,从业务对象Id到日志的TraceId,本文总结 ...

  3. 搞了一下午时间全浪费在这了,其实是自己拷贝了patch文件,导致tab变成了空格的错

    很老实的基于最新的kernel,源文件,修改了代码.通过diff -uNr --show-c-function dir1 dir2 > ipv6.patch制作了patch文件,准备代码上库构建 ...

  4. shell中数组及其相关操作

    转载 https://blog.csdn.net/jerry_1126/article/details/52027539

  5. DBX error:Driver could not be properly initialized .... 解决办法

    系统: win7 64位+ MySql 将libmysql.dll和Dbxmys.dll 拷到 C:\Windows\SysWOW64 目录. ( 64位系统)     32位则拷到  c:\wind ...

  6. Java多线程之实现Runnable接口

    package org.study2.javabase.ThreadsDemo.runnable; /** * @Auther:GongXingRui * @Date:2018/9/18 * @Des ...

  7. C#使用WebClient下载文件到本地目录

    C#使用WebClient下载文件到本地目录. 1.配置本地目录路径 <appSettings> <!--文件下载目录--> <add key="Downloa ...

  8. Servlet3.0上传

    1.上传对表单限制 *method=post *Enctype=multipart/form-data,它的默认值是:application/x-www-form-urlencoded 表单中需要添加 ...

  9. windows下ping端口

    上图的操作完成以后  进入dos控制台 输入telnet  ip地址  端口号   回车 标识已ping通 ping不通是这种提示

  10. reshape

    reshape 编辑 reshape是一种函数,函数可以重新调整矩阵的行数.列数.维数.在matlab命令窗口中键入doc reshape或help reshape即可获得该函数的帮助信息. B = ...