P3379 【模板】最近公共祖先(LCA)
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
输入输出样例
说明
时空限制: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<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; const int N=5e5+7; int n,Enum,m,s; int front[N],fat[N][20],deep[N]; struct node { int v,nxt; } e[N<<1]; int qread() { int x=0; char ch=getchar(); while(ch<'0' || ch>'9') ch=getchar(); while(ch>='0' && ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x; } void Insert(int u,int v) { e[++Enum].v=v; e[Enum].nxt=front[u]; front[u]=Enum; } void dfs(int x) { int v; for(int i=front[x]; i; i=e[i].nxt) { v=e[i].v; if(v==fat[x][0]) continue; fat[v][0]=x; deep[v]=deep[x]+1; dfs(v); } } void find_father() { for(int j=1; j<=19; j++) for(int i=1; i<=n; i++) fat[i][j]=fat[fat[i][j-1]][j-1]; } int Lca(int a,int b) { if(deep[a]<deep[b]) swap(a,b); int tmp=deep[a]-deep[b]; for(int i=0; i<=19; i++) if(tmp&(1<<i)) a=fat[a][i]; if(a==b) return a; for(int i=19; i>=0; i--) if(fat[a][i]!=fat[b][i]) { a=fat[a][i]; b=fat[b][i]; } return fat[a][0]; } int main() { scanf("%d%d%d",&n,&m,&s); int u,v; for(int i=1; i<=n-1; i++) { u=qread(); v=qread(); Insert(u,v); Insert(v,u); } dfs(s); find_father(); for(int i=1; i<=m; i++) { u=qread(); v=qread(); printf("%d\n",Lca(u,v)); } return 0; }
如果你不开心,那我就把右边这个帅傻子分享给你吧,
你看,他这么好看,那么深情的望着你,你还伤心吗?
真的!这照片盯上他五秒钟就想笑了。
一切都会过去的。