Nearest Common Ancestors
Nearest Common Ancestors
题目大意:给你k组数据,每组数据输入一个树和一组询问,询问树上LCA。
注释:n<=10000。
想法:咳咳,我初学LCA,先来一道裸题压压惊。LCA?(Least Common Ancestors),是指最近公共祖先。最近公共祖先?是指他们的祖先中距离它们最近者。我们在此介绍一种方法:朴素法。记录一个根节点,由根节点起记录深度。对于一组询问x,y,不妨设deep[x]>deep[y]。显然,任意一个i使得deep[i]<deep[y]都一定不是x和y的LCA。所以,我们先将x移动到和y同样的深度。现在,x和y在同意深度,此时,我们想到,将x和y同时向上移动,知道x==y。这时朴素法求LCA,也是最简单的求LCA的方法。
最后,附上丑陋的代码... ...
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define N 10010 5 using namespace std; 6 int fa[N],to[N],head[N],next[N]; 7 bool v[N]; 8 int deep[N]; 9 int tot; 10 void add(int x,int y)//链式前向星加边 11 { 12 to[++tot]=y; 13 next[tot]=head[x]; 14 head[x]=tot; 15 } 16 void dfs(int x,int pre,int step)//dfs处理深度和父亲节点 17 { 18 fa[x]=pre;deep[x]=step; 19 for(int i=head[x];i;i=next[i]) dfs(to[i],x,step+1); 20 } 21 int lca(int x,int y)//求lca。 22 { 23 if(deep[x]<deep[y]) swap(x,y); 24 while(deep[x]>deep[y]) x=fa[x];//将x移动到和y平齐 25 while(x!=y) x=fa[x],y=fa[y];//两个点一起向上走 26 return x; 27 } 28 int main() 29 { 30 int n; 31 int cases; 32 int a,b; 33 int root; 34 int x,y; 35 scanf("%d",&cases); 36 while(cases--) 37 { 38 tot=0; 39 memset(v,false,sizeof(v)); 40 // memset(deep,0,sizeof(deep)); 41 memset(head,0,sizeof(head));//必须清 42 // memset(fa,0,sizeof(fa)); 43 scanf("%d",&n); 44 for(int i=1;i<n;i++) 45 { 46 scanf("%d%d",&a,&b); 47 add(a,b);//加边 48 v[b]=1; 49 } 50 for(int i=1;i<=n;i++)//我想直接处理出根节点,因为我加的是单向边 51 { 52 if(!v[i]) 53 { 54 root=i; 55 break; 56 } 57 } 58 dfs(root,root,0); 59 scanf("%d%d",&x,&y); 60 printf("%d\n",lca(x,y)); 61 } 62 return 0; 63 }
小结:LCA是一个有意思的点,它包含了一些奇特的性质,在此先不做介绍。
错误:1.清数组是只需要清tot和head[]数组。
2.如果加的是单向边,必须预处理根节点。
| 欢迎来原网站坐坐! >原文链接<