[Poj]1330——最近公共祖先

[题目大意]
  • 给定一棵有根树和一个询问,求LCA

[分析题解]
  •  倍增,用F[I,J]表示第I个点的第2^J个父亲是哪位
  • 在BFS过程中可以一起处理出来
  • 然后先把两点上升到同一高度
  • 之后就是倍增找LCA的部分

[个人代码]
View Code
 1 //10191779      perseawe        1330    Accepted        1740K   16MS    Pascal  1957B   2012-05-13 20:51:00
 2 
 3 Const
 4   MaxN=10000+100;
 5 
 6 Var
 7   n,p,q,ans,tot,root,CaseNum:Longint;
 8   hv,Hit,lv,line:Array [0..MaxN] of Longint;
 9   f:Array [0..MaxN,0..15of Longint;
10   Edge:Array [0..MaxN] of Record wh,next:Longint;end;
11 
12 Procedure AddEdge(u,v:Longint);
13   begin
14     inc(tot);
15     Edge[tot].next:=hv[u];hv[u]:=tot;
16     Edge[tot].wh:=v;
17   end;
18 
19 Procedure Init;
20   var
21     I,u,v:longint;
22   begin
23     Readln(n);
24     tot:=0;Fillchar(hv,sizeof(hv),0);
25     Fillchar(Hit,Sizeof(Hit),0);
26     For I:=1 to N-1 do
27       begin
28         readln(u,v);
29         Inc(Hit[v]);
30         AddEdge(u,v);
31       end;
32     For I:=1 to N do
33       If Hit[I]=0 then
34         Root:=I;
35     readln(p,q);
36   end;
37 
38 Procedure BFS;
39   var
40     i,u,v,top,tail,tnode:Longint;
41   begin
42     Fillchar(lv,Sizeof(lv),0);
43     top:=0;tail:=1;Line[1]:=Root;
44     Repeat
45       inc(top);
46       u:=Line[top];
47       tnode:=hv[u];
48       while tnode<>0 do
49         begin
50           v:=Edge[tnode].wh;
51           inc(tail);
52           Line[tail]:=v;
53           lv[v]:=lv[u]+1;
54           f[v,0]:=u;
55           for i:=1 to trunc(ln(lv[v])/ln(2)+0.001do f[v,i]:=f[f[v,i-1],i-1];//预处理F数组部分
56           tnode:=Edge[tnode].next;
57         end;
58     Until top=tail;
59   end;
60 
61 Procedure Main;
62   var
63     i,t,lpq:Longint;
64   begin
65     Fillchar(f,Sizeof(F),0);
66     BFS;
67     if lv[p]<lv[q] then begin t:=p;p:=q;q:=t;end;//方便处理
68     lpq:=lv[p]-lv[q];
69     for i:=15 downto 0 do//上升部分
70       if lpq and (1 shl i)<>0 then
71         p:=f[p,i];
72     if p=q then begin ans:=p;exit;end;//特判!
73     for i:=15 downto 0 do//倍增找LCA部分
74       if f[p,i]<>f[q,i] then
75         begin
76           p:=f[p,i];
77           q:=f[q,i];
78         end;
79     ans:=f[p,0];//倍增完后两点都在LCA的下一层
80   end;
81 
82 Procedure Print;
83   begin
84     writeln(ans);
85   end;
86 
87 Begin
88   {$IFDEF LD}Assign(INPUT,'P1330.in');Reset(INPUT);{$ENDIF}
89   readln(CaseNum);
90   While Not(CaseNum=0do
91     begin
92   Init;
93   Main;
94   Print;
95   Dec(CaseNum);
96     end;
97   {$IFDEF LD}Close(INPUT);{$ENDIF}
98 

 


[相关链接] 
  1.  

[启发总结]
  1.  
posted @ 2012-05-13 22:02  PerSeAwe  阅读(393)  评论(0编辑  收藏  举报