您的位置:首页 > 其它

【RMQ&LCA】Nearest Common Ancest…

2015-02-02 19:25 344 查看
【RMQ&LCA】Nearest Common
Ancestors(最近公共祖先)
Time Limit:1000MS  Memory
Limit:65536KTotal Submit:4 Accepted:4
Description
最近公共祖先(lca.pas/c/cpp)【问题描述】    有根树是一个在计算机科学和工程学中众所周知的数据结构。如下图所示的例子:    在上图,每个结点用1-16中的一个整数标记。结点8是这棵树的根。  一个结点x是一个结点y的祖先当且仅当结点x是在根和结点y的路径上。例如,结点4是结点16的祖先,结点10也是结点16的祖先。实际上,结点8,4和12都是结点16的祖先。记住每个结点都是它自己的祖先。结点8,4,6和7都是结点7的祖先。    一个结点x被称做结点y和z的公共祖先当且仅当x都是y和z的祖先。因此,结点8 和4是结点16和7的公共祖先。  一个结点x被称做结点y和z的最近公共祖先当且仅当x是y和z的一个公共祖先且在y和z的所有公共祖先中是最近的。所以,结点16和7的最近公共祖先是结点4,因为结点4比结点8更接近结点16和7。  在其它例子中,结点2和3的最近公共祖先结点10,结点6和13的最近公共祖先是结点8,结点4和12的最近公共祖先是结点4。在最后的一个例子中,如果y是z的一个祖先,那么y和z的最近公共祖先是y。    写一个程序找出在一棵树中两个不同结点的最近公共祖先。Input
输入包括T组数据。第一行是一个整数T。对每组数据,第一行是一个整数N,表示这棵树的结点数,其中2<=N<=10,000。这些结点标记为1,2,…,N。接下来的N-1行包括一对整数,代表一条边,第一个数是第二个数的父亲。保证N个结点恰好有N-1条边。最后的一行包括两个不同的整数,表示要求最近公共祖先的两个不同结点Output
对每组数据输出一行,包括一个表示所求的两个不同结点的最近公共祖先的整数Sample
Input


Sample
Output


Hint
本题数据不完整,请在本系统测试通过后到http://poj.org/problem?id=1330
提交完整测试!Source
Taejon 2002 设三个数组:f数组记录树的遍历,d数组记录深度 var m,n,nf,father,j,l,r:longint; f,d:array[0..20001]of longint; tree:array[1..10001,0..101]of longint;procedure init;var i,x,y:longint; mark:array[1..10001]of boolean;begin fillchar(mark,sizeof(mark),0); fillchar(tree,sizeof(tree),0); fillchar(f,sizeof(f),0); fillchar(d,sizeof(d),0); read(n); for i:=1 to n-1 do  begin  read(x,y);  inc(tree[x,0]);  tree[x,tree[x,0]]:=y;  mark[y]:=true;  end; read(l,r); for i:=1 to n do  if not mark[i] then  begin  father:=i;  exit;  end;end;procedure dfs(fa,de:longint);var i:longint;begin inc(f[0]); f[f[0]]:=fa; d[f[0]]:=de; for i:=1 to tree[fa,0] do begin  dfs(tree[fa,i],de+1); inc(f[0]); f[f[0]]:=fa; d[f[0]]:=de; end;end;function min(x,y:longint):longint;begin if x<y then exit(x)       
else exit(y);end;procedure main;var i,t,b,ll,rr,minn,mini:longint;begin nf:=2*n-1; for i:=1 to nf do  if f[i]=l then begin ll:=i; break; end; for i:=1 to nf do  if f[i]=r then begin rr:=i; break; end; if rr<ll then  begin  rr:=rr+ll;  ll:=rr-ll;  rr:=rr-ll;  end; minn:=maxlongint; for i:=ll to rr do  if d[i]<minn then begin
minn:=d[i]; mini:=i; end; writeln(f[mini]);end;begin read(m); for j:=1 to m do  begin  init;  dfs(father,0);  main;  end;end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: