题意:

有nnn个城市,mmm条连接两个城市的道路,每条道路有一个海拔hih_{i}hi​和长度lil_{i}li​。目前这些城市正发洪水,小明家在节点1,他现在需要回家。他有一辆自行车,但这个自行车只能在没有被水淹的道路骑行。对于每条道路,如果道路的海拔不高于当日的水位线,那么这条路就会被淹。小明如果需要经过一条被淹的道路,则需要丢弃他的自行车,然后徒步过去,自行车如果被丢弃了就不能被找回来了。有qqq次询问,每次询问给出小明目前所在的位置xxx和当日水位线hhh,问他回家最少需要步行多长距离?可以认为小明无论骑车还是步行都是无限快的,也就是他回到家之前水位线都是不变的。

Solution:

显然有一些边是不能经过的,并且海拔越低的边越不能经过,所以考虑KruskalKruskalKruskal重构树,由路的海拔为关键词从大到小加入重构树,那么对于目前所在的节点xxx和当日海拔hhh,我们找到一个uuu,满足

val[u]>h,val[fa[u]]<=hval[u]>h,val[fa[u]]<=h val[u]>h,val[fa[u]]<=h

那么这颗以uuu为根的子树的所有点都是我们能够到达的,现在问题是,我们该从哪个我们能到达的节点开始步行回去呢?我们在子树内找到任意一个点,到1的最短路可以计算出来,但又如何减去骑车的部分呢?不妨考虑这样的情况,有一个点AAA,和一副

连通图GGG,AAA不和图联通,定义两点距离为实际距离-在GGG图中经过的边权总和,也就是GGG图不需要花费,随便跑,那么到这个集合的某一点距离的最小值就应该是到这个图的点的实际距离的最小值。所以原问题就变成了uuu这颗子树的到1的最短路的最小值是多少,预处理源点为1的最短路,定义min1[i]min1[i]min1[i]为iii这棵子树的最小最短路距离,那么答案就是min1[u]min1[u]min1[u]了,找这个点倍增即可

// #include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<numeric>
using namespace std;using ll=long long;
const int N=400005,inf=0x3fffffff;
const long long INF=0x3f3f3f3f3f3f,mod=998244353;struct wway
{int u,v,l,h;
}eedge[N];struct graph
{struct way{int to,next,w;}edge[N<<2];int cnt,head[N<<1];void add(int u,int v,int w=0){edge[++cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;head[u]=cnt;}
}A,B;int f[N<<1];int find(int k)
{if(f[k]==k) return k;return f[k]=find(f[k]);
}bool vis[N];
ll dis[N];
int n,m,tot,val[N<<1],fa[N<<1][21],min1[N<<1];
priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>>q;void KruskalRebuild()
{sort(eedge+1,eedge+1+m,[&](const wway& x,const wway& y){return x.h>y.h;}); tot=n; A.cnt=0;for(int i=1;i<=n+m;i++){f[i]=i;A.head[i]=0;val[i]=0;}for(int i=1;i<=m;i++){auto& [u,v,l,h]=eedge[i];int pa=find(u),pb=find(v);if(pa==pb) continue;f[pa]=f[pb]=fa[pa][0]=fa[pb][0]=++tot;val[tot]=h;A.add(pa,tot); A.add(tot,pa);A.add(pb,tot); A.add(tot,pb);}
}void dijkstra()
{for(int i=1;i<=n;i++){dis[i]=numeric_limits<int>::max();vis[i]=false;}q.push({dis[1]=0,1});while(!q.empty()){int u=q.top().second; q.pop();if(vis[u]) continue;vis[u]=true;for(int i=B.head[u];i;i=B.edge[i].next){int v=B.edge[i].to,w=B.edge[i].w;if(dis[u]+w<dis[v]) q.push({dis[v]=dis[u]+w,v});}}
}
//A图是重构树,B图是原图
void dfs(int u,int fa)
{if(u<=n) min1[u]=dis[u];else min1[u]=numeric_limits<int>::max();for(int i=1;i<=20;i++) ::fa[u][i]=::fa[::fa[u][i-1]][i-1];for(int i=A.head[u];i;i=A.edge[i].next){int v=A.edge[i].to;if(v==fa) continue;dfs(v,u);min1[u]=min(min1[u],min1[v]);}
}ll solve(int x,int k)
{for(int i=20;i>=0;i--)if(fa[x][i]&&val[fa[x][i]]>k) x=fa[x][i];return min1[x];
}void work()
{cin>>n>>m; B.cnt=0;for(int i=1;i<=n;i++){dis[i]=numeric_limits<int>::max();B.head[i]=0;}for(int i=1;i<=m;i++){auto& [u,v,l,h]=eedge[i];scanf("%d%d%d%d",&u,&v,&l,&h);B.add(u,v,l); B.add(v,u,l);}dijkstra();KruskalRebuild();dfs(tot,0);int q,K,S; ll lastans=0; cin>>q>>K>>S;while(q--){int x,h; scanf("%d%d",&x,&h);x=((x+K*lastans)-1)%n+1;h=(h+K*lastans)%(S+1);printf("%lld\n",lastans=solve(x,h));}
}int main()
{// freopen("in.txt","r",stdin);int T; cin>>T;while(T--) work();return 0;
}

洛谷P4768 kruskal重构树相关推荐

  1. 洛谷P4768 [NOI2018]归程(Kruskal重构树)

    题意 直接看题目吧,不好描述 Sol 考虑暴力做法 首先预处理出从$1$到每个节点的最短路, 对于每次询问,暴力的从这个点BFS,从能走到的点里面取$min$ 考虑如何优化,这里要用到Kruskal重 ...

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

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

  3. LOJ.2718.[NOI2018]归程(Kruskal重构树 倍增)

    LOJ2718 BZOJ5415 洛谷P4768 Rank3+Rank1无压力 BZOJ最初还不是一道权限题... Update 2019.1.5 UOJ上被hack了....好像是纯一条链的数据过不 ...

  4. 浅谈kruskal重构树

    食用须知: *因为临时改动,代码不一定完全正确. *以下概念来自个人理解,并不十分准确.慎! <Kruskal重构树思想与模板> Kruskal算法(维护无向图的最小生成森林):每一时刻, ...

  5. kruskal重构树练习

    洛谷 P4197 Peaks 题意: 有 nnn 个山峰,每一个山峰高 hih_ihi​ ,有 mmm 条双向带权边将一些山峰连接起来,有 qqq 次询问,每次询问 (v,x,k)(v,x,k)(v, ...

  6. LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)

    LOJ 洛谷 这题不就是Peaks(加强版)或者归程么..这算是\(IOI2018\)撞上\(NOI2018\)的题了? \(Kruskal\)重构树(具体是所有点按从小到大/从大到小的顺序,依次加入 ...

  7. Kruskal重构树详解

    目录 Kruskal算法 Kruskal重构树 在学习重构树之前,我们要先熟悉一下基本的kruskal算法 Kruskal算法 首先给出一张有向图,让我们求最小生成树(用总权值最小的一些边的集合,使得 ...

  8. kruskal 重构树(讲解 + 例题)

    kruskal重构树 如何建树 模仿kruskalkruskalkruskal,先将所有边排序. 依次遍历每一条边,如果这条边的两个节点(u,vu, vu,v)不在同一个连通块里面, 则新建一个nod ...

  9. 洛谷P4768 [NOI2018]归程 [可持久化并查集,Dijkstra]

    题目传送门 归程 格式难调,题面就不放了. 分析: 之前同步赛的时候反正就一脸懵逼,然后场场暴力大战,现在呢,还是不会$Kruskal$重构树,于是就拿可持久化并查集做. 但是之前做可持久化并查集的时 ...

最新文章

  1. RHCS创建高可用集群apche服务器
  2. Java字符串indexOf(int ch,int fromIndex)方法,带示例
  3. 《Iterative-GAN》的算法伪代码整理
  4. delphi 异步 调用 带参数_如何在 Spring 异步调用中传递上下文
  5. Bootstrap 表单的帮助文本
  6. 2021年Tiktok用户增长和使用模式?
  7. 谷歌员工中位数年薪达 170 万元,却仍买不起房!
  8. 开源啦:连DeepMind也捉急的游戏,OpenAI给你攻破第一关的高分算法
  9. android中json解析及使用 (下)
  10. 深入了解Java ClassLoader、Bytecode 、ASM、cglib (I)
  11. [Swift]LeetCode188. 买卖股票的最佳时机 IV | Best Time to Buy and Sell Stock IV
  12. 数学建模-模糊数学模型
  13. 大数据之spark_spark SQL的建表语句
  14. Ticket管理工具:Redmine
  15. lpx寒假作业案例10
  16. 报错javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException
  17. Audio基本概念及处理流程
  18. HTML5+CSS3小实例:鼠标悬停发光按钮
  19. python thinker canvas详解_python thinker canvas create_arc 使用详解
  20. SQL DML操作之增删改查

热门文章

  1. InfoPath 如何使用 XML 技术
  2. NC6和NCC版本与微软AD域认证集成
  3. 如何格式化服务器系统,如何格式化服务器
  4. .[转] 趣味经济学
  5. 【C++进阶】哈希(万字详解)—— 运用篇(下)
  6. Vue中修改Mint UI的Toast默认样式问题 - 字体大小调整
  7. python定义函数时有多个return语句
  8. http://www.verycd.com/topics/55332/
  9. 2021年N1叉车司机报名考试及N1叉车司机免费试题
  10. gltf模型浏览器_ThreeJs作智慧城市项目后记