链接: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. source insight 中文乱码解决方法

    options->preferences -> Files-> default encoding: 选择 GB2312 CP:936

  2. android全屏/沉浸式状态栏下,各种键盘挡住输入框解决办法

    https://blog.csdn.net/smileiam/article/details/69055963

  3. Windows 2012 安装 SQL Server 2012,.Net Framework 3.5安装不成的解决办法

    This behavior can also be caused by a system administrator who configures the computer to use Window ...

  4. netmap配置

    1.配置流程 环境:centos 7.2.1511,内核版本3.10.0-327.el7.x86_64 [1]下载内核源码,https://buildlogs.cdn.centos.org/c7.15 ...

  5. Redis深入学习笔记(四)主从数据复制流程

    主从节点的数据复制是Redis高可用和高负载的重要基础,本篇介绍数据的主从复制流程. 数据复制策略: 全量复制:一般用于初次复制场景,Redis早期支持的复制功能只有全量复制,它会把主节点全部数据一次 ...

  6. MVC和WebApi的区别:

    1.mvc 和WebApi: 区别: a.MVC是建立网站的一种框架,倾向于返回用户的页面请求:webApi倾向于返回用户数据请求 b.mvc直接继承system.mvc.controller:web ...

  7. altium designer 制作内部不铺铜的封装,如三极管下面禁止铺铜

    制作封装的时候,按P键或菜单栏中点击place选项点选Polygon Pour Cutout.画一个原件禁止铺铜区域即可.

  8. 使用Linux的环境变量

    许多程序和脚本都使用环境变量来获取系统信息,并存储临时数据和配置信息: 1.什么是环境变量 用来存储关于shell会话和工作环境的信息,就叫做环境变量: bash shell下两种类型: 1.全局变量 ...

  9. python configparse模块&xml模块

    configparse模块 用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser. [DEFAULT] serveraliveinterval = ...

  10. sqlPlus基本操作

    SQL*PLUS连接方法 1. $ sqlplus "user/password[@service] [as sysdba]" 2. $ sqlplus /nolog SQL> ...