AC日记——【模板】最近公共祖先(LCA)洛谷 P3379
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数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 <algorithm> #define maxn 500001 using namespace std; struct EdgeType {
int to,next;
};
struct EdgeType edge[maxn<<]; int if_z,n,m,s,num,f[maxn],deep[maxn];
int belong[maxn],size[maxn],cnt,head[maxn]; char Cget; inline void read_int(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(int from,int to)
{
edge[++num].to=from,edge[num].next=head[to],head[to]=num;
edge[++num].to=to,edge[num].next=head[from],head[from]=num;
} void search(int now,int fa)
{
int pos=cnt++;
f[now]=fa,deep[now]=deep[fa]+;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==fa) continue;
search(edge[i].to,now);
}
size[now]=cnt-pos;
} void search_(int now,int chain)
{
int pos=;
belong[now]=chain;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==f[now]) continue;
if(size[pos]<size[edge[i].to]) pos=edge[i].to;
}
if(pos!=) search_(pos,chain);
else return ;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==pos||edge[i].to==f[now]) continue;
search_(edge[i].to,edge[i].to);
}
} inline int lca(int x,int y)
{
while(belong[x]!=belong[y])
{
if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
x=f[belong[x]];
}
if(deep[x]<deep[y]) return x;
else return y;
} int main()
{
read_int(n),read_int(m),read_int(s);
int from,to;
for(int i=;i<n;i++)
{
read_int(from),read_int(to);
edge_add(from,to);
}
search(s,),cnt=,search_(s,s);
for(int i=;i<=m;i++)
{
read_int(from),read_int(to);
printf("%d\n",lca(from,to));
}
return ;
}
附,70分暴力找lca:
#include <cstdio>
#include <algorithm> #define maxn 500001 using namespace std; struct EdgeType {
int to,next;
};
struct EdgeType edge[maxn<<]; int f[maxn],head[maxn],num;
int n,m,s,if_z,dfn[maxn],cnt; char Cget; inline void read_int(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(int from,int to)
{
edge[++num].to=from,edge[num].next=head[to],head[to]=num;
edge[++num].to=to,edge[num].next=head[from],head[from]=num;
} void search(int now,int fa)
{
dfn[now]=++cnt,f[now]=fa;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==fa) continue;
search(edge[i].to,now);
}
} inline int lca(int x,int y)
{
if(dfn[x]<dfn[y]) swap(x,y);
while(dfn[x]>dfn[y]) x=f[x];
while(dfn[y]>dfn[x]) y=f[y];
return y;
} int main()
{
read_int(n),read_int(m),read_int(s);
int from,to;
for(int i=;i<n;i++)
{
read_int(from),read_int(to);
edge_add(from,to);
}
search(s,);
for(int i=;i<=m;i++)
{
read_int(from),read_int(to);
printf("%d\n",lca(from,to));
}
return ;
}
AC日记——【模板】最近公共祖先(LCA)洛谷 P3379的更多相关文章
- [模板] 最近公共祖先/lca
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...
- AC日记——[ZJOI2015]幻想乡战略游戏 洛谷 P3345
[ZJOI2015]幻想乡战略游戏 思路: 树剖暴力转移: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1 ...
- AC日记——[JLOI2014]松鼠的新家 洛谷 P3258
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前 ...
- AC日记——[USACO15DEC]最大流Max Flow 洛谷 P3128
题目描述 Farmer John has installed a new system of pipes to transport milk between the stalls in his b ...
- AC日记——[USACO10MAR]仓配置Barn Allocation 洛谷 P1937
[USACO10MAR]仓配置Barn Allocation 思路: 贪心+线段树维护: 代码: #include <bits/stdc++.h> using namespace std; ...
- AC日记——[HNOI2010]BOUNCE 弹飞绵羊 洛谷 P3203
[HNOI2010]BOUNCE 弹飞绵羊 思路: SBlct: 代码: #include <bits/stdc++.h> using namespace std; #define max ...
- AC日记——斐波那契数列 洛谷 P1962
斐波那契数列 思路: 矩阵快速幂: 来,上代码: #include <cstdio> #include <cstring> #include <iostream> ...
- AC日记——[USACO09JAN]全流Total Flow 洛谷 P2936
题目描述 Farmer John always wants his cows to have enough water and thus has made a map of the N (1 < ...
- AC日记——[USACO11DEC]牧草种植Grass Planting 洛谷 P3038
题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...
- AC日记——让我们异或吧 洛谷 P2420
题目描述 异或是一种神奇的运算,大部分人把它总结成不进位加法. 在生活中…xor运算也很常见.比如,对于一个问题的回答,是为1,否为0.那么: (A是否是男生 )xor( B是否是男生)=A和B是否能 ...
随机推荐
- redis学习笔记(2)
redis学习笔记第二部分 --配置文件介绍 二,解析redis的配置文件redis.conf常见配置参数说明redis.conf 配置项说明如下:1. Redis默认不是以守护进程的方式运行,可以通 ...
- XML 转 fastJSON
import java.util.List; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.Doc ...
- linux :没有找到 ifconfig netstat
linux :没有找到 ifconfig netstat ubuntu sudo apt install net-tools -y centos yum install net-tools
- paper:synthesizable finite state machine design techniques using the new systemverilog 3.0 enhancements 之 FSM Coding Goals
1.the fsm coding style should be easily modifiable to change state encoding and FSM styles. FSM 的的 状 ...
- 使用laravel框架的eloquent\DB模型连接多个数据库
1.配置.env文件 DB_HOST_TRAILER=127.0.0.1DB_PORT_TRAILER=3306DB_DATABASE_TRAILER=htms_trailerDB_USERNAME_ ...
- python 面对对象基础
目录 面向对象基础 面向对象编程(抽象) 类与对象 给对象定制独有的特征 对象的属性查找顺序 类与对象的绑定方法 类与数据类型 对象的高度整合 面向对象基础 面向对象编程(抽象) 回顾一下 面向过程编 ...
- AD采样求平均STM32实现
iADC_read(, &u16NTC_1_Sample_Val_ARR[]); == ui8FirstSampleFlag) { ; i<; i++) { u16NTC_1_Sampl ...
- luogu2293 [JSOI2008]Blue Mary开公司
ref好像叫什么李超线段树?--这篇不是太通用-- #include <iostream> #include <cstdio> #include <cmath> u ...
- loj2254 「SNOI2017」一个简单的询问
ref #include <algorithm> #include <iostream> #include <cstdio> #include <cmath& ...
- luogu2763 试题库问题
倘若某个试题已经被选到某个类型里了,那么它就不可再被选进别的类型了. 所以,对于每个类型,我们将其与汇连边,权值是它的要求的题目数量. 对于每个题目,我们将源与其连边,权值是1,代表只能用一次.然后再 ...