洛谷 P3379 【模板】最近公共祖先(LCA)
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
输入输出样例
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
4
4
1
4
4
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000
样例说明:
该树结构如下:

第一次询问:2、4的最近公共祖先,故为4。
第二次询问:3、2的最近公共祖先,故为4。
第三次询问:3、5的最近公共祖先,故为1。
第四次询问:1、2的最近公共祖先,故为4。
第五次询问:4、5的最近公共祖先,故为4。
故输出依次为4、4、1、4、4。
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
long long read()
{
long long x=,f=;
char ch=getchar();
while(ch>''||ch<'')
{
if(ch=='-')
f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
const int maxn=;
int n,m,s,k,a,b;
int head[maxn],d[maxn],p[maxn][];
struct node
{
int v,next;
} e[maxn*];
void add(int u,int v)
{
e[k].v=v;
e[k].next=head[u];
head[u]=k++;
}
void dfs(int u,int fa)
{
d[u]=d[fa]+;
p[u][]=fa;
for(int i=; (<<i)<=d[u]; i++)
p[u][i]=p[p[u][i-]][i-];
for(int i=head[u]; i!=-; i=e[i].next)
{
int v=e[i].v;
if(v!=fa)
dfs(v,u);
}
}
int lca(int a,int b)
{
if(d[a]>d[b])
swap(a,b);
for(int i=; i>=; i--)
if(d[a]<=d[b]-(<<i))
b=p[b][i];
if(a==b)
return a;
for(int i=; i>=; i--)
{
if(p[a][i]==p[b][i])
continue;
else
a=p[a][i],b=p[b][i];
}
return p[a][];
}
int main()
{
memset(head,-,sizeof(head));
n=read(),m=read(),s=read();
for(int i=; i<n; i++)
{
a=read(),b=read();
add(a,b);
add(b,a);
}
dfs(s,);
for(int i=; i<=m; i++)
{
a=read(),b=read();
printf("%d\n",lca(a,b));
}
return ;
}
倍增求LCA
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=2e6+;
#define ls k<<1
#define rs k<<1|1
long long read()
{
long long x=,f=;
char ch=getchar();
while(ch>''||ch<'')
{
if(ch=='-')
f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
struct node
{
int v,nxt;
} e[maxn];
int head[maxn],fa[maxn],deep[maxn],tot[maxn],son[maxn],top[maxn];
int num=,cnt;
void add(int x,int y)
{
e[num].v=y;
e[num].nxt=head[x];
head[x]=num++;
}
int dfs1(int now,int f,int dep)
{
deep[now]=dep;
fa[now]=f;
tot[now]=;
int maxson=-;
for(int i=head[now]; i; i=e[i].nxt)
{
if(e[i].v==f)
continue;
tot[now]+=dfs1(e[i].v,now,dep+);
if(tot[e[i].v]>maxson)
maxson=tot[e[i].v],son[now]=e[i].v;
}
return tot[now];
}
void dfs2(int now,int topf)
{
top[now]=topf;
if(!son[now])
return ;
dfs2(son[now],topf);
for(int i=head[now]; i; i=e[i].nxt)
if(e[i].v!=son[now]&&e[i].v!=fa[now])
dfs2(e[i].v,e[i].v);
}
int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
swap(x,y);
x=fa[top[x]];
}
if(deep[x]>deep[y])
swap(x,y);
return x;
}
int main()
{
memset(head,,sizeof(head));
int n=read(),m=read(),root=read();
for(int i=; i<=n-; i++)
{
int x=read(),y=read();
add(x,y),add(y,x);
}
dfs1(root,,);
dfs2(root,root);
while(m--)
{
int x=read(),y=read();
printf("%d\n",LCA(x,y));
}
return ;
}
树链剖分求LCA
洛谷 P3379 【模板】最近公共祖先(LCA)的更多相关文章
- [模板] 最近公共祖先/lca
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...
- 【树链剖分】洛谷P3379 树链剖分求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 图论2 最近公共祖先LCA
模板 吸取洛谷P3379的教训,我决定换板子(其实本质都是倍增是一样的),把vector换成了边表 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下 ...
- 最近公共祖先 lca (施工ing)
声明 咳咳,进入重难点的图论算法之一(敲黑板): 题目: 洛谷 P3379 先放标程,施工ing,以后补坑!!!(实在太难,一个模板这么长 [ 不过好像还是没有 AC自动机 长哎 ],注释都打半天,思 ...
- 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 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- 【lhyaaa】最近公共祖先LCA——倍增!!!
高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...
- 洛谷P3379 【模板】最近公共祖先(LCA)
P3379 [模板]最近公共祖先(LCA) 152通过 532提交 题目提供者HansBug 标签 难度普及+/提高 提交 讨论 题解 最新讨论 为什么还是超时.... 倍增怎么70!!题解好像有 ...
随机推荐
- https协议的简单理解
本片文章梳理三个知识点: 1.对称加密和非对称加密的区别 2.https协议的请求流程 3.http协议和https协议的区别 一.对称加密和非对称加密 对称加密:加密和解密使用同一密钥. 非对称加密 ...
- (二)校园信息通微信小程序从后台获取首页的数据笔记
在从后台获取数据之前,需要先搭建好本地服务器的环境. 确保Apache,MySql处于开启状态.下图为Apache,MySql处于开启时状态 然后进入后台管理平台进行字段和列表的定义 然后在后台添加数 ...
- vue知多少,你对vue的认识比别人高在哪?
1.beforeCreated/created区别? beforeCreated钩子能干什么 2.data中使用props 3.get/set依赖收集 get收集依赖(观察者) set 观察者重新求值 ...
- 快速查看linux命令的用法----------TLDR
之前我们如果用一个命令,但是忘了具体的参数是什么的时候,通常会用man,比如 man tar 但是man有时候特别的冗长,你要找到想要的例子非常困难,所以tldr命令就是一个很好的补充,里边会有经常用 ...
- dubbo负载均衡与集群集群容错
1.负载均衡 在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 random 随机调用. 1. 负载均衡策略 Random LoadBalance 随机,按权重设置随机概率.(默认值)在一个 ...
- mysl 常用函数 union all if ifnull exists case when
1.union all UNION 操作符用于合并两个或多个 SELECT 语句的结果集.请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时,每条 S ...
- ssh-copy-id 拷贝用户秘钥
生成秘钥 ssh-keygen -t [rsa|dsa] 将会生成密钥文件和私钥文件 id_rsa,id_rsa.pub或id_dsa,id_dsa.pub 将 .pub 文件复制到B机器的 .ssh ...
- 题解-CodeChef IOPC14L Sweets Problem
Problem CodeChef-IOPC14L 题目概要:给定 \(n\) 种糖果且给定每种糖果的数量 \(A_i\),\(Q\) 组询问,每次问选出 \(S\) 个糖果的方案数(模\(10^9+7 ...
- 023_supervisorctl管理服务注意事项
一. (1)问题 我在线上使用supervisorctl管理服务时遇到程序文件更新了,但是下次supervisorctl执行的时候并没有更新, 原因是supervisor更新后必须重新读取加载文件才行 ...
- Python爬虫基础之认识爬虫
一.前言 爬虫Spider什么的,老早就听别人说过,感觉挺高大上的东西,爬网页,爬链接~~~dos黑屏的数据刷刷刷不断地往上冒,看着就爽,漂亮的校花照片,音乐网站的歌曲,笑话.段子应有尽有,全部都过来 ...