题面见洛谷

难点:  走过有积水的地方之后就需计算路径长了

关键算法:   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 归程的更多相关文章

  1. noip 2018 day1 T1 铺设道路 贪心

    Code: #include<cstdio> using namespace std; int main() { int last=0,ans=0; int n;scanf("% ...

  2. [LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程

    [LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程 题意 给定一张无向图, 每条边有一个距离和一个高度. 再给定 \(q\) 组可能在线的询问, 每组询问给定一个点 ...

  3. NOI 2018 酱油记

    转眼离 NOI 2018 已经过了一个星期了,退役的我还是随便来水水吧. 语法.错字之类的可能会很多,但是我也不拘这点小节了. 恭喜 yww, zjt, sk 进队,zwl, myh au , yay ...

  4. [LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字

    [LOJ 2720][BZOJ 5417][UOJ 395][NOI 2018]你的名字 题意 给定一个大串 \(S\) 以及 \(q\) 次询问, 每次询问给定一个串 \(T\) 和区间 \([l, ...

  5. [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士

    [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士 题意 题面好啰嗦啊直接粘LOJ题面好了 小 D 最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照 ...

  6. Noip2011 提高组 Day1 T1 铺地毯 + Day2 T1 计算系数

    Day1 T1 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小 ...

  7. Noip2014 提高组 Day1 T1 生活大爆炸版石头剪刀布 + Day2 T1 无线网络发射器选址

    Day1 T1 题目描述 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一样,则不分胜负.在<生活大爆炸>第二季第8 集中出现了一种石头剪刀布的升级版游戏. 升 ...

  8. 「BalkanOI 2018 Day1」Election

    「BalkanOI 2018 Day1」Election 记C为1,T为-1,\(sum[i]\)为\(i\)点的前缀和. 对于询问\([l,r]\),分两步计算答案. 要求所有点的\(sum[i]- ...

  9. 「BalkanOI 2018 Day1」Minmaxtree

    「BalkanOI 2018 Day1」Minmaxtree 每个点都有一个最大和最小权值的限制. 然后每一个权值的限制都必须要取到. 每个点显然可以直接让他取到最大或最小权值. 可以想到每个点匹配一 ...

随机推荐

  1. 怒转一波,此人整理的Flink特别好

    Apache Flink:特性.概念.组件栈.架构及原理分析 Apache Flink是一个面向分布式数据流处理和批量数据处理的开源计算平台,它能够基于同一个Flink运行时(Flink Runtim ...

  2. <每日一题>题目4:for循环套生成器的面试题

    题目: def add(n,i): return n+i def test(): for i in range(4): yield i g = test() for n in [1,10,5]: g ...

  3. redis缓存架构-02-两种持久化机制(RDB和AOF)

    1.两种持久化机制的介绍 1.1 RDB 周期性的生成redis内存数据的一份完整的快照 1)根据配置的检查点,生产rdb快照文件,fork一个子线程,将数据dump到rdb快照文件中,完成rdb文件 ...

  4. flex 的经典用法

    Document   11 21 31 41 51 61 71 81 91 101 111 121 131 141 151 161 171 181 191 201 211 221 231 241 25 ...

  5. WPFのStyle TargetType的不同写法

    一.隐式写法 <Style TargetType="TextBlock"> <Setter Property="/> </Style> ...

  6. 【知识强化】第五章 输入/输出(I/O)管理 5.1 I/O管理概述

    这门课的最后一个章节——设备管理. 操作系统它作为系统资源的管理者,既需要对上层的软件进行管理,也需要对下层的硬件进行管理.操作系统它需要对处理机还有存储器这些硬件进行管理,但是这些硬件其实是在计算机 ...

  7. CentOS 6.5安装aria2(转载)

    CentOS 6.5安装aria2 由于yum install aria2无法找到安装包,试了好几个源,都找不到,于是自己找了一些地址: 1.下载安装包: # wget http://ftp.tu-c ...

  8. unittest接口自动化测试报告

    unittest接口自动化测试报告 展示: 代码: __author__ = "Wai Yip Tung, Findyou" __version__ = "0.8.2.1 ...

  9. SurfaceView的基本使用(转)

    转自:https://www.cnblogs.com/zhangyingai/p/7087371.html SurfaceView的基本使用   一.引入: Android提供了View来进行绘图处理 ...

  10. 深度探索C++对象模型第四章:函数语义学

    C++有三种类型的成员函数:static/nonstatic/virtual 一.成员的各种调用方式 C with class 只支持非静态成员函数(Nonstatic member function ...