标签:pen 模版 ext text 公共祖先 color ret swap dfs
给出一棵根节点为1的树,每次询问两点之间的最近公共祖先。
第一行一个整数n表示树的节点个数
第二行n-1个数,第i个数表示点(i+1)的父亲是哪个点。保证第i个数<=i。
第三行一个整数m表示询问个数。
接下来m行,每行有俩整数,表示询问的俩点。
共m行,对于每次询问输出最近公共祖先的编号。
给出一棵根节点为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
6 1 2 1 2 4 3 3 5 6 4 2 6
2 4 1
#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
标签:pen 模版 ext text 公共祖先 color ret swap dfs
原文地址:http://www.cnblogs.com/12fs/p/7351755.html