链接:https://ac.nowcoder.com/acm/contest/549/F
来源:牛客网

题目描述

小A这次来到一个景区去旅游,景区里面有N个景点,景点之间有N-1条路径。小A从当前的一个景点移动到下一个景点需要消耗一点的体力值。但是景区里面有两个景点比较特殊,它们之间是可以直接坐观光缆车通过,不需要消耗体力值。而小A不想走太多的路,所以他希望你能够告诉它,从当前的位置出发到他想要去的那个地方,他最少要消耗的体力值是多少。

输入描述:

第一行一个整数N代表景区的个数。
接下来N-1行每行两个整数u,v代表从位置u到v之间有一条路径可以互相到达。
接下来的一行两个整数U,V表示这两个城市之间可以直接坐缆车到达。
接下来一行一个整数Q,表示有Q次询问。
接下来的Q行每行两个整数x,y,代表小A的位置在x,而他想要去的地方是y。

输出描述:

对于每个询问下x,y输出一个结果,代表x到y消耗的最少体力对于每个询问下x,y输出一个结果,代表x到y消耗的最少体力
示例1

输入

4
1 2
1 3
2 4
3 4
2
1 3
3 4

输出

1
0 解题思路:很明显是lca的板子题,唯一不同的就是加了一条权值为零的边而已,我们假设边x-y权值为零,需要求u-v的最小距离,dis【i,j】为i到j的最小距离,此时u-v的最小距离为min(dis【u,v】,min(dis【u,x】+dis【y,v】,dis【u,y】+dis【x,v】))了。
在这,我就简单讲一下lca的RMQ的求法吧。
两个结点的最近公共祖先的求法:

就如上面的一棵树,我们按DFS遍历一遍,把遍历到的结点加入到某个数组中可以得到一个序列:1 2 4 2 5 7 9 7 5 8 5 2 1 3 6 3 1
他们的深度依次为:                                  0 1 2 1 2 3 4 3 2 3 2 1 0 1 2 1 0
要查找某两个结点的最近公共祖先,即查找这这个序列中两个结点所对应的这一段的深度最小的那个结点。比如查找5和6的最近公共祖先,他们对应的结点序列为:
5 7 9 7 5 8 5 2 1 3 6,深度为
2 3 4 3 2 3 2 1 0 1 2,深度最小为1结点(深度为0)。这里可以使用RMQ来维护(当然也可以用线段树),不熟悉RMQ的可以看:传送门。(感觉讲的很渣啊。。。)
当然,求lca的还有别的方法,等以后有机会再更新吧(目前不会QAQ)。
这里贴上本题的AC代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
#define ri register int
typedef long long ll; inline ll gcd(ll i,ll j){
return j==?i:gcd(j,i%j);
}
inline ll lcm(ll i,ll j){
return i/gcd(i,j)*j;
}
inline void read(int &x){
char ch=x=;
int f=;
while(!isdigit(ch)){
ch=getchar();
if(ch=='-'){
f=-;
}
}
while(isdigit(ch))
x=x*+ch-'',ch=getchar();
x=x*f;
}
const int maxn=3e5+;
struct st1{
int to,w;
st1():to(),w(){
}
st1(int to,int w):to(to),w(w){
}
};
vector<st1> vec[maxn];
int dep[maxn];
int in[maxn*];//某个点在欧拉序第一次出现的位置
int co;
int vis[maxn];
int st[maxn*][];//存运行dfs时候的序列(好像叫欧拉序)
void dfs(int u,int cnt){
vis[u]=;
st[++co][]=u;
in[u]=co;
dep[u]=cnt;
for(int i=;i<vec[u].size();i++){
st1 tem=vec[u][i];
if(vis[tem.to]==){
dfs(tem.to,cnt+);
st[++co][]=u;
}
}
}
void getst(){
for(int i=;(<<i)<=co;i++){
for(int be=;be+(<<i)-<=co;be++){
if(dep[st[be][i-]]<dep[st[be+(<<(i-))][i-]]){
st[be][i]=st[be][i-];
}
else{
st[be][i]=st[be+(<<(i-))][i-];
}
}
}
}
int rmq(int l,int r){
int x=in[l];
int y=in[r];
if(x>y)swap(x,y);
int tem=floor(log(y-x+)/log());
int tem1=st[x][tem];
int tem2=st[y-(<<tem)+][tem];
if(dep[tem1]<dep[tem2])return tem1;
else return tem2;
}
int main(){
int n;
int u,v;
co=;
read(n);
for(int i=;i<n;i++){
read(u);read(v);
vec[u].push_back(st1(v,));
vec[v].push_back(st1(u,));
}
read(u);read(v);
int k;
dfs(,);
getst();
scanf("%d",&k);
int x,y;
for(int i=;i<k;i++){
read(x);read(y);
int ans;
ans=dep[x]+dep[y]-*dep[rmq(x,y)];
ans=min(ans,dep[x]+dep[u]-*dep[rmq(x,u)]+dep[y]+dep[v]-*dep[rmq(y,v)]);
ans=min(ans,dep[x]+dep[u]-*dep[rmq(y,u)]+dep[y]+dep[v]-*dep[rmq(x,v)]);
printf("%d\n",ans);
}
return ;
}

牛客小白月赛13 小A的最短路(lca+RMQ)的更多相关文章

  1. 牛客小白月赛13 小A的回文串(Manacher)

    链接:https://ac.nowcoder.com/acm/contest/549/B来源:牛客网 题目描述 小A非常喜欢回文串,当然我们都知道回文串这种情况是非常特殊的.所以小A只想知道给定的一个 ...

  2. 牛客小白月赛13 小A买彩票 (记忆化搜索)

    链接:https://ac.nowcoder.com/acm/contest/549/C来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言52428 ...

  3. 牛客小白月赛13 小A的柱状图(单调栈)

    链接:https://ac.nowcoder.com/acm/contest/549/H来源:牛客网 题目描述 柱状图是有一些宽度相等的矩形下端对齐以后横向排列的图形,但是小A的柱状图却不是一个规范的 ...

  4. 单调栈+前缀和 || Nowcoder || 牛客小白月赛13 || 小A的柱状图

    题面:小A的柱状图 题解:无 代码: #include<cstdio> #include<cstring> #include<iostream> #define l ...

  5. 牛客小白月赛13-J小A的数学题 (莫比乌斯反演)

    链接:https://ac.nowcoder.com/acm/contest/549/J来源:牛客网 题目描述 小A最近开始研究数论题了,这一次他随手写出来一个式子,∑ni=1∑mj=1gcd(i,j ...

  6. 牛客小白月赛6 I 公交线路 最短路 模板题

    链接:https://www.nowcoder.com/acm/contest/136/I来源:牛客网 题目描述 P市有n个公交站,之间连接着m条道路.P市计划新开设一条公交线路,该线路从城市的东站( ...

  7. 牛客小白月赛13 G(双向搜索)

    AC通道 两边同步搜,一步里面A走一次B走两次,遇到对方走过的地方就得到了答案. #include <bits/stdc++.h> using namespace std; const i ...

  8. 牛客小白月赛13 E(图、矩阵幂)

    AC通道 如果建立第一天某点到某点有几条路的矩阵,做k次矩阵乘就是第k天某点到某点有几条路.统计即可. #include <bits/stdc++.h> using namespace s ...

  9. 【牛客小白月赛21】NC201605 Bits

    [牛客小白月赛21]NC201605 Bits 题目链接 题目描述 Nancy喜欢做游戏! 汉诺塔是一个神奇的游戏,神奇在哪里呢? 给出3根柱子,最开始时n个盘子按照大小被置于最左的柱子. 如果盘子数 ...

随机推荐

  1. tab$被删除恢复指南

    by 蔡建良 2019-2-25 经过长时间摸索,参考网上各类文章.今天终于让我成功恢复了oracle的sys.tab$表,并成功打开了数据库. 将此过程记录下来,与大家共享.如有疑问可联系我QQ: ...

  2. spring从服务器磁盘读取图片,然后显示于前端页面上

    需求是,前台通过传参,确定唯一图片,然后后台在服务器磁盘中读取该图片,然后显示于前台页面上. 后台代码: @RequestMapping("unit/bill/showeinvoice&qu ...

  3. ADT工具使用详解

    备注:一下内容为本人手工翻译官方文档注解,如有翻译不到位的地方,欢迎批评指正; ADT(Android开发工具)是Eclipse的插件,它提供了一套与Eclipse IDE集成的工具.它可以让您访问许 ...

  4. adb相关指令 笔记

      adb相关指令 笔记 1.adb devices 查看物理测试设备或模拟器的相关信息,有三个状态: (1)device 设备已连接到adb服务器上,但该状态并不代表设备已启动完毕可以进行操作: ( ...

  5. wordpress中安装插件需要ftp服务

    曾经天真的以为要装个ftp,然后发现这只是wordpress为了安全而留下的坑,只要修改wordpress配置即可 wordpress安装目录 ==> wp-config.php,文件添加以下代 ...

  6. java 日志脱敏框架 sensitive-新版本0.0.2-深度拷贝,属性为对象和集合的支持

    项目介绍 日志脱敏是常见的安全需求.普通的基于工具类方法的方式,对代码的入侵性太强.编写起来又特别麻烦. 本项目提供基于注解的方式,并且内置了常见的脱敏方式,便于开发. 用户也可以基于自己的实际需要, ...

  7. Javascript面向对象编程(一)

    什么是面向对象? 它是一种新的编程模式.以往的面向过程是将功能都写在一起,逐行实现.面向对象与其不同,它只关心对象提供的功能,而不在乎细节. 面向对象的特点? 抽象:抓住问题的核心,贯穿始终: 封装: ...

  8. Oracle降低高水位先(转载)

    Oracle  降低高水位线的方法 高水位(HIGH WARTER MARK,HWM)好比水库中储水的水位,用于描述数据库中段的扩展方式.高水位对全表扫描方式有着至关重要的影响.当使用DELETE删除 ...

  9. c#控件 menuStrip(转)

    一.概述 菜单通过存放按照一般主题分组的命令将功能公开给用户. MenuStrip 控件是此版本的 Visual Studio 和 .NET Framework 中的新功能.使用该控件,可以轻松创建  ...

  10. PHP批量保存图片

    关于这个问题网上也有回答,我只是把我在工作中用到的代码分解出来,供需要的朋友使用.以下代码都已经经过测试,所以没有任何问题.有问题请加QQ:1127173874 第一部分 数据库表结构 create ...