NOI 2018 Day1 T1 归程
难点: 走过有积水的地方之后就需计算路径长了
关键算法: kruskal重构树
①原来的 kruskalkruskalkruskal 算法就是用并查集实现的,
但当我们使用 kruskal重构树的时候,
对于每次找出的不同的两个连通块的祖先,
我们都新建一个点作为两个祖先的父亲,并将当前边的边权转化为新点的点权(或指向该点的边的边权)。
②因为kruskal是贪心加边,所以对于该题来说,
如果在重构树上能从一个点抵达另一个点,那么在原图上也一定可以
③如果我们以海拔为第一关键字对边进行从大到小的排序,然后修建 kruskal重构树,
这样就弄出了一颗以海拔为关键字的小根堆。
然后对于每一棵子树,如果询问中的水位线是低于子树的根节点的,
那么此时这棵子树中的所有叶子结点都是连通的。
放到题中就是说这颗子树中任选一个点出发,
到子树中的其它点都不需要花费。(此段来自洛谷题解)
④对于每个询问,我们只需要找到该点无需花费就能走到的点(用预处理好的倍增找)中,哪个离目的地(1号点)更近,
这个预处理一下最短路就是了
上代码:
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define rg register
#define _ 200001
#define a(x) edge[x].a
#define l(x) edge[x].l
#define u(x) heap[x].u
#define it(x) heap[x].it
#define min(x,y) x<y?x:y;
using namespace std;
int n,m,record[_<<],exist[_],num_of_edges,an[_<<][],minn[_<<][],cnt,dad[_<<];
long long dis[_],New_dis[_<<];
bool used[_];
struct ppp
{
int x,y,a;
}way[_<<];
struct pp
{
int next,to,l,a;
}edge[_<<];
struct pppp
{
int u,it;
}heap[];
inline int read()
{
rg int save=,w=;rg char q=getchar();
while(q<''||q>''){if(q=='-')w=-;q=getchar();}
while(q>=''&&q<='')save=(save<<)+(save<<)+q-'',q=getchar();
return save*w;
}
inline void add(rg int from,rg int to,rg int ll,rg int aa)
{
edge[++num_of_edges]=(pp){record[from],to,ll,aa};
record[from]=num_of_edges;
}
int tail;
inline void put(rg int i,rg int ww)
{
u(++tail)=i,it(tail)=ww;
rg int d=tail;
while(d>)
{
if(it(d)<it(d>>))swap(heap[d],heap[d>>]),d>>=;
else
break;
}
}
inline void cut()
{
heap[]=heap[tail--];
it(tail+)=;
rg int d=;
while(d<tail)
{
rg int pointer=it(d<<)<it(d<<|)?(d<<):(d<<|);
if(it(d)>it(pointer))swap(heap[d],heap[pointer]),d=pointer;
else break;
}
}
int find(rg int x){if(x!=dad[x])dad[x]=find(dad[x]);return dad[x];}
inline void dijkstra()
{
for(rg int i=;i<=n;++i)used[i]=;
dis[]=;
put(,dis[]);
rg int k=;
while(tail)
{
rg pppp ss=heap[];
cut();
if(used[ss.u])continue;
used[ss.u]=;
k++;
for(rg int j=record[ss.u];j;j=edge[j].next)
{
rg int to=edge[j].to;
if(dis[to]>dis[ss.u]+edge[j].l)
{
dis[to]=dis[ss.u]+edge[j].l;
put(to,dis[to]);
}
}
if(k==n-)break;
}
}
inline bool Cwen(rg ppp x,rg ppp y){return x.a>y.a;}
int ceng;
void dfs(rg int);
inline void Kruskal()
{
rg int i,j;
for(i=;i<=(n<<);++i)dad[i]=i;
sort(way+,way+m+,Cwen);
for(i=;i<=m;++i)
{
rg int fx=find(way[i].x),fy=find(way[i].y);
if(fx!=fy)//重构树
{
add(++cnt,fx,,way[i].a);//(++cnt):新建节点
add(cnt,fy,,way[i].a);//因为之后的操作只需要从根节点遍历下来,故不建反向边
dad[fx]=dad[fy]=cnt;
if(cnt==(n<<)-)break;
}
}
ceng=log(cnt)/log();
for(i=;i<=cnt;++i)
{
if(i<=n)New_dis[i]=dis[i];
for(j=;j<=ceng;++j)
an[i][j]=,minn[i][j]=;
}
for(i=n+;i<=cnt;++i)New_dis[i]=;
//这个题目里不要找LCA,depth[]也就不需要
an[cnt][]=;//聊胜于无的一句话
dfs(cnt);//预处理点之间的最小海拔
}
void dfs(rg int i)
{
for(rg int j=;j<=ceng;++j)
{
an[i][j]=an[an[i][j-]][j-];
minn[i][j]=min(minn[i][j-],minn[an[i][j-]][j-]);
}
if(i<=n)return;//免得走到原来的图上了(在重构树里<=n的就是叶子节点,无需继续遍历)
for(rg int j=record[i];j;j=edge[j].next)
{
rg int to=edge[j].to;
if(to!=an[i][])
{
an[to][]=i;
minn[to][]=a(j);
dfs(to);
New_dis[i]=min(New_dis[i],New_dis[to]);
}
}
}
inline int jump(rg int i,rg int p)
{
for(rg int j=ceng;j>=;--j)
if(minn[i][j]>p)i=an[i][j];
return i;
}
int main()
{
rg int t=read();
while(t--)
{
n=read(),m=read();
rg int i,j;
tail=;
for(i=;i<=n;++i)dis[i]=;
for(i=;i<=(n<<);++i)it(i)=;
num_of_edges=;
for(i=;i<=(n<<);++i)record[i]=;
for(i=;i<=m;++i)
{
rg int u=read(),v=read(),l=read(),a=read();
add(u,v,l,a),add(v,u,l,a);
way[i]=(ppp){u,v,a};
}
dijkstra();
cnt=n;
Kruskal();//重构树,以海拔为关键字从大到小排序,保证可以判断一个点是否能被无耗遍历到
rg int Q=read(),K=read(),S=read();
long long lastans=;
for(i=;i<=Q;++i)
{
rg int v=read(),p=read();
v=(v+K*lastans-)%n+;
p=(p+K*lastans)%(S+);
rg int to=jump(v,p);
lastans=New_dis[to];
printf("%lld\n",lastans);
} }
return ;
}
NOI 2018 Day1 T1 归程的更多相关文章
- noip 2018 day1 T1 铺设道路 贪心
Code: #include<cstdio> using namespace std; int main() { int last=0,ans=0; int n;scanf("% ...
- [LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程
[LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程 题意 给定一张无向图, 每条边有一个距离和一个高度. 再给定 \(q\) 组可能在线的询问, 每组询问给定一个点 ...
- NOI 2018 酱油记
转眼离 NOI 2018 已经过了一个星期了,退役的我还是随便来水水吧. 语法.错字之类的可能会很多,但是我也不拘这点小节了. 恭喜 yww, zjt, sk 进队,zwl, myh au , yay ...
- [LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字
[LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字 题意 给定一个大串 \(S\) 以及 \(q\) 次询问, 每次询问给定一个串 \(T\) 和区间 \([l, ...
- [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士
[LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士 题意 题面好啰嗦啊直接粘LOJ题面好了 小 D 最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照 ...
- Noip2011 提高组 Day1 T1 铺地毯 + Day2 T1 计算系数
Day1 T1 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小 ...
- Noip2014 提高组 Day1 T1 生活大爆炸版石头剪刀布 + Day2 T1 无线网络发射器选址
Day1 T1 题目描述 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一样,则不分胜负.在<生活大爆炸>第二季第8 集中出现了一种石头剪刀布的升级版游戏. 升 ...
- 「BalkanOI 2018 Day1」Election
「BalkanOI 2018 Day1」Election 记C为1,T为-1,\(sum[i]\)为\(i\)点的前缀和. 对于询问\([l,r]\),分两步计算答案. 要求所有点的\(sum[i]- ...
- 「BalkanOI 2018 Day1」Minmaxtree
「BalkanOI 2018 Day1」Minmaxtree 每个点都有一个最大和最小权值的限制. 然后每一个权值的限制都必须要取到. 每个点显然可以直接让他取到最大或最小权值. 可以想到每个点匹配一 ...
随机推荐
- Unity接入AbMob踩坑记
之前是配置好的环境,不知道怎么突然就不正常了. 一直弹出下面的报错: Error running CocoaPods. Please ensure you have at least version ...
- 案例:使用xml存储数据
HTML: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- foobar2000 频谱给我的win10 任务栏添加一点会动背景
在任务栏右键,"任务栏设置",颜色 -> 透明效果, 然后 foobar2000 的 view -> layout -> Quick Setup,选择带有Visu ...
- shell脚本学习(2)查找
1 grep 用法: grep -F fa 找含有fa字符的字符串 yuyuyu@ubuntu:~$ grep -F fa < do.txt grep -i fa 忽略大 ...
- 使用nexus3.10搭建maven私有仓库
使用nexus3.10搭建maven私有仓库-----详见如下链接-- --此贴用于笔记 https://blog.csdn.net/vipbupafeng/article/details/80232 ...
- Linux 下虚拟机——Virtual Box
下面介绍几款可以在Linux下运行的虚拟机 VMware,VirtualBox, QEMU, Xen.(其中我只用过VirtualBox 和Xen, 我是新手,其他两个没时间折腾,所以下面的资料都几乎 ...
- [CSP-S模拟测试52]题解
A.平均数 看到第K小,又确定跟平衡树/主席树没有关系,可以把问题转化为有K-1个答案比它小再考虑二分. 二分平均值x,之后将原序列统一减去x.这时序列中区间和<0的区间个数就是原序列中平均值小 ...
- [jzoj5840]Miner 题解(欧拉路)
首先考虑第一问.每个联通块的情况是相对独立的,所以可以分别求每个联通块的答案.无向图中存在欧拉路的条件是奇点数为0或2,那么合法方案肯定是tp到一个奇点,通过一条欧拉路到另一个奇点,再tp到另一个奇点 ...
- 微信小程序学习笔记(三)--框架-逻辑层
逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈. 开发者写的所有代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁.这一行为类似 Service ...
- 【Java架构:基础技术】一篇文章搞掂:Gradle
前言 Gradle是什么: Gradle提供了一个域特定语言(DSL),用于描述构建 它使用 Groovy 语言,使其更容易来形容和构建 Gradle 中的每一个构建脚本使用UTF-8进行编码保存,并 ...