首页 > 代码库 > LCA
LCA
A LCA-2 摸底考
背景&&描述
给出一棵根节点为1的树,每次询问两点之间的最近公共祖先。
输入格式
第一行一个整数n表示树的节点个数
第二行n-1个数,第i个数表示点(i+1)的父亲是哪个点。保证第i个数<=i。
第三行一个整数m表示询问个数。
接下来m行,每行有俩整数,表示询问的俩点。
输出格式
共m行,对于每次询问输出最近公共祖先的编号。
样例输入
A LCA-2 摸底考
背景&&描述
给出一棵根节点为1的树,每次询问两点之间的最近公共祖先。
输入格式
第一行一个整数n表示树的节点个数
第二行n-1个数,第i个数表示点(i+1)的父亲是哪个点。保证第i个数<=i。
第三行一个整数m表示询问个数。
接下来m行,每行有俩整数,表示询问的俩点。
输出格式
共m行,对于每次询问输出最近公共祖先的编号。
样例输入
6 1 2 1 2 4 3 3 5 6 4 2 6
样例输出
2 4 1
数据范围与约定
- 对于100%的数据:
6 1 2 1 2 4 3 3 5 6 4 2 6
样例输出
2 4 1
数据范围与约定
- 对于100%的数据:
#include<cstdio> #include<algorithm> #include<cstring> const int N=200050; struct node { int to,next; }e[N]; int first[N],dep[N],visit[N]; int fa[N][30]; int cnt=0; void insert(int u,int v) { e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt; e[++cnt].to=u;e[cnt].next=first[v];first[v]=cnt; } void dfs(int x) { visit[x]=1; for(int i=1;(1<<i)<=dep[x];i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int k=first[x];k;k=e[k].next) if(!visit[e[k].to]) { fa[e[k].to][0]=x; dep[e[k].to]=dep[x]+1; dfs(e[k].to); } } int getlca(int x,int y) { if(dep[x]<dep[y]) std::swap(x,y); int t=dep[x]-dep[y]; for(int i=0;(1<<i)<=t;i++) if((1<<i)&t) x=fa[x][i]; for(int i=25;i>=0;i--) if((1<<i)<=dep[x]&&fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; if(x==y) return x; return fa[x][0]; } int main() { int n; scanf("%d",&n); int k; for(int i=2;i<=n;i++) scanf("%d",&k),insert(i,k); dfs(1); int m; scanf("%d",&m); int p,q; for(int i=1;i<=m;i++) scanf("%d %d",&p,&q),printf("%d\n",getlca(p,q)); return 0; }
------------------------
LCA模版
谢谢brain551的教导;
可以去看他的博客,贼好.
-------------------------
这个一道基本上一模一样的题:
给出一棵以1为根的有n个节点的树。
m个询问,每次询问a与b的最近公共祖先。
----------------------
要LCA理解的可以去看看:
http://www.cnblogs.com/yyf0309/p/5972701.html
LCA
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。