P3379 最近公共祖先(LCA) 洛谷
题意简单明了(这就是个模板)。
就是让我们找2个节点的公共祖先而已,但我们要讲的做法不是生硬的爆搜,而且直接搜好像过不去……
这次就讲我往后拖了n多天才开始学了倍增LCA。
嗯,这个题,如果2个节点的深度是不一样的,我们要把他们的深度变成一样的,变成一样的以后就开始倍增搜索。
上面的这句话为我们点明了这个题的解题方法,我们要求出每个节点的深度,每个节点2的几次方个祖先是谁,还有这棵树是什么样子的(一开始我把第一个输入的当成爸爸,wa的老惨了)。
首先第一步:创建这颗树
题目中给出了树的根节点,所以说,和根节点连接的就是第二层的节点,和第二次节点连接的就是第三层的节点……和第n-1层连接的就是第n层的节点。
虽然这个的实现很简单,但如果有同学不会,可以戳这里。
树建完了,开始第二步:查找一个节点第2的i次方个祖先是谁?
有个神奇的东西叫做RMQ,和这个差不多,懂了可以去秒一下。
我们可以通过一个生活实例来思考,比如你爸爸就是你第2^0个祖先,你第2^1的祖先就是你爸爸的爸爸,你的第2^2个祖先就是你爷爷的爷爷……
可以发现,我们要求的东西可以通过已知的东西获得,这就避免了一些奇怪的模拟。
现在树建完了,每个子节点的祖先也知道了,接下来就是倍增模拟了:
就像上面说的一样,先把2个位置统一公共祖先,然后寻找。
思路都讲完了,直接放代码了:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
long long n,m,s,a,b;
long long cf[100],wz,shu=1;
long long lca[500005][30],sd[500005];
long long ans,head[500005];
struct hehe
{
long long nxt,wei;
}sz[1000005];
int add(int tou,int wei)//链式前向星真香
{
ans++;
sz[ans].wei=wei;
sz[ans].nxt=head[tou];
head[tou]=ans;
}
int dfs(int qd,int bb)//搜深度的地方
{
lca[qd][0]=bb;
for(int i=1;(1<<i)<=sd[qd];i++)//没必要就不搜了,很明白的道理嘛
{
lca[qd][i]=lca[lca[qd][i-1]][i-1];//想想祖孙三代的例子或许就明白这句话了。
}
for(int i=head[qd];i!=0;i=sz[i].nxt)//链式前向星的查找
{
if(sz[i].wei!=bb)//因为不知道谁是谁的爸爸,所以要特判一下。
{
sd[sz[i].wei]=sd[qd]+1;
dfs(sz[i].wei,qd);
}
}
}
long long start(long long x,long long y)
{
if(sd[x]<sd[y])//永远让x的深度
{
swap(x,y);
}
int i=0;
while((1<<i)<=sd[x])
{
i++;
}
i--;
if(sd[x]!=sd[y])//不等于就大步的往前走
{
for(int j=i;j>=0;j--)
{
if(sd[lca[x][j]]>=sd[y])//小心不要走过。
{
x=lca[x][j];
}
}
}
if(x==y)//x是y的子节点呢,没事了,直接输出。
{
return x;
}
for(int j=i;j>=0;j--)
{
if(lca[x][j]!=lca[y][j])//这个依旧不要走过
{
x=lca[x][j];
y=lca[y][j];
}
}
return lca[x][0];//因为倍增的奇妙,最后一定会停留在答案的下一层,上升一层就可以了。
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&s);//正常的读入
sd[s]=1;
lca[s][0]=0;
for(int i=0;i<n-1;i++)
{
scanf("%lld%lld",&a,&b);
add(a,b);
add(b,a);
}
dfs(s,0);
for(int i=0;i<m;i++)
{
scanf("%lld%lld",&a,&b);
printf("%lld\n",start(a,b));//正常的运算和输出
}
return 0;
}
这个题就到这里吧,讲完了。
P3379 最近公共祖先(LCA) 洛谷的更多相关文章
- Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)
Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...
- POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)
POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
- [模板] 最近公共祖先/lca
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...
- 【lhyaaa】最近公共祖先LCA——倍增!!!
高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...
- P3379最近公共祖先(LCA)
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 最近公共祖先 lca (施工ing)
声明 咳咳,进入重难点的图论算法之一(敲黑板): 题目: 洛谷 P3379 先放标程,施工ing,以后补坑!!!(实在太难,一个模板这么长 [ 不过好像还是没有 AC自动机 长哎 ],注释都打半天,思 ...
- 图论2 最近公共祖先LCA
模板 吸取洛谷P3379的教训,我决定换板子(其实本质都是倍增是一样的),把vector换成了边表 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下 ...
- 求最近公共祖先(LCA)的各种算法
水一发题解. 我只是想存一下树剖LCA的代码...... 以洛谷上的这个模板为例:P3379 [模板]最近公共祖先(LCA) 1.朴素LCA 就像做模拟题一样,先dfs找到基本信息:每个节点的父亲.深 ...
随机推荐
- Windows 程序设计(3) 关于字符串
1. 宽窄字节的区别及重要性 1.1 宽窄字节简介: C语言/C++语言,使用的字符串指针就是 char* 类型,C++中的字符串是 string,内部也是对 char* 的封装 窄字节 其实最早的系 ...
- 12.实战交付一套dubbo微服务到k8s集群(5)之交付dubbo-monitor到K8S集群
dubbo-monitor官方源码地址:https://github.com/Jeromefromcn/dubbo-monitor 1.下载dubbo-monitor源码并解压 [root@hdss7 ...
- C# 什么是泛型 ?以及对泛型各方面的一些知识点的整理
1.1 理解什么是泛型 在.NET 2.0,可以成为革命性壮举的, 就是引入了激动人心的特性——泛型..NET泛型是CLR和高级语言共同支持的一种全新的结构,实现了一种将类型抽象化的通用处理方式.在泛 ...
- Centos7下的MySQL5.6安装
yum install wget yum install perl perl-devel cd /usr/local/src wget https://cdn.mysql.com//Downloads ...
- 30_栈的定义.swf
上面的局部变量 i int*p中的p指针变量,是在栈中分配的,malloc申请的内存是在堆中分配的,动态申请的都在堆中分配的. 栈是一种数据存储的结果,先进后出的数据结构.
- 一起玩转微服务(12)——揭密starter
介绍 Spring Boot的starter主要用来简化依赖用的,对于企业级开发中的与第三方的集成,可以通过一段简单的配置来完成,这样开发人员无需再对包依赖的问题头疼.Spring Boot为我们提供 ...
- Python三大器之生成器
Python三大器之生成器 生成器初识 什么是生成器 生成器本身属于迭代器.继承了迭代器的特性,惰性求值,占用内存空间极小. 为什么要有生成器 我们想使用迭代器本身惰性求值的特点创建出一个可以容纳百万 ...
- ThinkPHP5使用PHPExcel实现数据导出功能
1.将PHPExcel类库文件夹放入extend目录下 2.导出功能实现 public function download(){ if(request()->isPost()){ $val = ...
- Day11-微信小程序实战-交友小程序-附近的人(地图的形式)及位置获取
回顾:在下面的tabbar中,我们已经实现了首页 消息 我的,就剩下”附近“页面了 ”附近“的页面主要是用地图来进行展示的(可以显示我的位置,也可以显示周围附近的人的位置) (在地图里面点击它的头像的 ...
- 洛谷 P5683 【[CSPJX2019]道路拆除】
先用做的暴力,因为n最多才3000嘛,但是后来发现时间复杂度不止\(O\)(\({n}^2\)),然后就放弃了. 讲讲我的暴力+错误思路吧: 把1到s1和s2的最短路算出来,用SPFA,然后用DFS求 ...