题面见洛谷

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

关键算法:   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. 如何使用 C++ Inja html template 模板

    C++ html template Inja是现代C ++的模板引擎,受到jinja for python的启发.它有一个简单而强大的模板语法,包含所有变量,循环,条件,包含,回调,您需要的注释,嵌套 ...

  2. Java Console/控制台 打印表格

    功能:控制台打印表格,支持字段动态长度,左对齐,右对齐,居中,设置最大列长,设置列间隔符,设置最多打印多少行. 类下载地址:http://download.csdn.net/download/j506 ...

  3. Redis 设置权限密码,以及如何开启关闭设置

    linux redis 设置密码:   在服务器上,这里以linux服务器为例,为redis配置密码. 1.第一种方式 (当前这种linux配置redis密码的方法是一种临时的,如果redis重启之后 ...

  4. linux c 链接详解1-多目标文件链接

    1. 多目标文件的链接 摘自:linux c编程一站式学习 http://learn.akae.cn/media/index.html 可以学会在linux下将多个c语言文件一起编译. 现在我们把例  ...

  5. ThreadLocal简单使用示例

    ThreadLocal为每个线程提供单独的数据副本,线程间的数据为自身线程所独有(不存在共享变量问题),直接看代码 public class ThreadLocalTest { private sta ...

  6. 转 Tomcat访问日志详细配置

    配置http访问日志.Tomcat自带的能够记录的http访问日志已经很详细了取消下面这段的注释: <Valve className="org.apache.catalina.valv ...

  7. 全栈开发React-私有路由

    demo import React from 'react'; import {Route,Redirect} from 'react-router-dom' import {connect} fro ...

  8. cpanle/Apache 强制http跳转到https

    因为租的虚拟主机是使用Cpanel,按照网上找的文章,处理的步骤如下: 打开Cpanel面板-文件管理器-设置(在页面的右上角)-勾选显示隐藏文件(dotfiles)-save . 找到网站所在的目录 ...

  9. Python3.5-20190513-廖老师-自我笔记-函数式编程

    把复杂的任务拆成各个小的函数,通过函数的调用来完成任务.这就是面向过程编程. 高阶函数:就是让函数的参数能够接收别的函数.把函数作为参数传入到另一个函数. 函数名也是变量.和变量用法一样的,指向一个函 ...

  10. 斯特林数&斯特林反演

    第一类斯特林数 定义 第一类Stirling数\(s(n,m)\),也可记为\(\begin{bmatrix}n\\m\end{bmatrix}\). 第一类Stirling分为无符号第一类Stirl ...