[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..15] of 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.001) do 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=0) do
91 begin
92 Init;
93 Main;
94 Print;
95 Dec(CaseNum);
96 end;
97 {$IFDEF LD}Close(INPUT);{$ENDIF}
98
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..15] of 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.001) do 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=0) do
91 begin
92 Init;
93 Main;
94 Print;
95 Dec(CaseNum);
96 end;
97 {$IFDEF LD}Close(INPUT);{$ENDIF}
98
[相关链接]
[启发总结]
——————————————————————————————————————
你说,我们的存在,永不消逝。对吧?
如果,我们都在努力创造了存在。我们,会幸福的。对吧?