题意:给一张无向联通图,每条边有长度和高度,每次询问在高度大于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. E: 无法打开锁文件 /var/lib/dpkg/lock-frontend - open (13: 权限不够)E: 无法获取 dpkg 前端锁 (/var/lib/dpkg/lock-frontend),请查看您是否正以 root 用户运行?

    一.解决方案 修改root密码,以root身份安装 sudo pwdroot root  # 输入新密码即可

  2. K8S、云计算、大数据、编程语言

    云计算.大数据.编程语言学习指南下载,100+技术课程免费学!这份诚意满满的新年技术大礼包,你Get了吗?-云栖社区-阿里云https://yq.aliyun.com/articles/691028 ...

  3. bat 文本合并

    小工具—把多个TXT文件合成一个 - TTXS_RS的博客 - CSDN博客https://blog.csdn.net/TTXS_RS/article/details/79743384 把所有文本文件 ...

  4. cent6.x配置主机名及静态网络

    # 修改网卡名为NAME="eth0" [root@jenkins ~]# -persistent-net.rules # This file was automatically ...

  5. ssm项目跨域访问

    最近使用ssm开发了一个项目,为了项目的开发速度,采用的是前后端同时开发,所以前端文件没有集成在项目中,最后在调试时涉及到了跨域.跨域的解决方法很多,我采用的是最简单的一种,代码如下: 新建一个过滤器 ...

  6. NIO服务器与客户端

    这里客户端没有采用NIO形式 服务器: package com.util.Server.NIO; import javax.print.DocFlavor;import java.io.IOExcep ...

  7. vue 思維導圖

    vue概念:vue是一個輕量級的javascript庫:是一種漸進式的框架:vue可以實現數據視圖雙向綁定. vue基礎語法:實例化.條件.循環 vue重頭戲:動畫.組件.過濾.ajax.自定義組件. ...

  8. 循环神经网络RNN及LSTM

    一.循环神经网络RNN RNN综述 https://juejin.im/entry/5b97e36cf265da0aa81be239 RNN中为什么要采用tanh而不是ReLu作为激活函数?  htt ...

  9. 算法题 -- 输入一个Long数组,按要求输出一个等长的Long数组

    /** * 输入一个Long数组,按要求输出一个等长的Long数组 * 输出数组的元素值等于,输入数组除相同下标外其他元素的积 * 如:输入[1, 2, 3, 4], 输出[24, 12, 8, 6] ...

  10. CSS3 flexbox 布局 ---- flex项目属性介绍

    现在介绍用在flex项目上的css 属性,html结构还是用ul, li 结构,不过内容改成1,2,3, 样式的话,直接把给 ul 设display:flex 变成flex 容器,默认主轴的方向为水平 ...