LCA倍增算法的错误与模板
先上我原来的错误的代码
type
node=^link;
link=record
num:int64;
next:node;
end; var
fa:array[..,..] of int64;
dep:array[..] of int64;
nd:array[..] of node;
b:array[..] of boolean;
dl:array[..] of int64;
n,m,maxdep,ans,t1,t2:int64;
i:longint; procedure maketree;
var
t1,t2,head,tail:int64;
i,j:longint;
p:node;
begin for i:= to n do
b[i]:=false; for i:= to n- do
begin
read(t1,t2); new(p);
p^.num:=t2;p^.next:=nd[t1];nd[t1]:=p;
new(p);
p^.num:=t1;p^.next:=nd[t2];nd[t2]:=p;
end; new(p);
head:=;tail:=;dl[head]:=;b[]:=true;
while head<=tail do
begin
p:=nd[dl[head]]; while p<>nil do
begin
if b[p^.num]=false then
begin
inc(tail);
dl[tail]:=p^.num;
fa[p^.num,]:=dl[head];
dep[p^.num]:=dep[dl[head]]+;
b[p^.num]:=true;
if dep[p^.num]>maxdep then maxdep:=dep[p^.num];
end;
p:=p^.next;
end; inc(head);
end; for j:= to trunc(ln(maxdep)/ln())+ do
for i:= to n do
if dep[i]>=<<j then
fa[i,j]:=fa[fa[i,j-],j-];
end; procedure lca(a,b:longint);
var
i,t:longint;
begin
if dep[a]>dep[b] then
begin
t:=a;
a:=b;
b:=t;
end; if dep[a]<>dep[b] then
for i:=trunc(ln(dep[b]-dep[a])/ln()) downto do
if dep[b]-<<i>=dep[a] then
begin
b:=fa[b,i];
ans:=ans+<<i;
end; if a<>b then
for i:=trunc(ln(dep[a])/ln()) downto do
if fa[a,i]<>fa[b,i] then
begin
a:=fa[a,i];
b:=fa[b,i];
ans:=ans+<<(i+);
end; if a<>b then inc(ans,);
end; begin readln(n); if n= then
begin
writeln();
halt;
end; maketree; readln(m); read(t1);
for i:= to m do
begin
read(t2); lca(t1,t2);
t1:=t2;
end; writeln(ans); end.
这个写法WA了一个点,答案比标准答案大。
最后发现可能是ln出现了误差,导致结果偏小,使两点无法移到同层。在后面的移动中无论怎样都无法移到同点,使答案比原来大二
改正后的模板
type
node=^link;
link=record
num:int64;
next:node;
end; var
fa:array[..,..] of int64;
dep:array[..] of int64;
nd:array[..] of node;
b:array[..] of boolean;
dl:array[..] of int64;
n,m,maxdep,ans,t1,t2:int64;
i:longint; procedure maketree;
var
t1,t2,head,tail:int64;
i,j:longint;
p:node;
begin for i:= to n do
b[i]:=false; for i:= to n- do
begin
read(t1,t2); new(p);
p^.num:=t2;p^.next:=nd[t1];nd[t1]:=p;
new(p);
p^.num:=t1;p^.next:=nd[t2];nd[t2]:=p;
end; new(p);
head:=;tail:=;dl[head]:=;b[]:=true;
while head<=tail do
begin
p:=nd[dl[head]]; while p<>nil do
begin
if b[p^.num]=false then
begin
inc(tail);
dl[tail]:=p^.num;
fa[p^.num,]:=dl[head];
dep[p^.num]:=dep[dl[head]]+;
b[p^.num]:=true;
if dep[p^.num]>maxdep then maxdep:=dep[p^.num];
end;
p:=p^.next;
end; inc(head);
end; for j:= to trunc(ln(maxdep)/ln())+ do
for i:= to n do
if dep[i]>=<<j then
fa[i,j]:=fa[fa[i,j-],j-];
end; procedure lca(a,b:longint);
var
i,t:longint;
begin
if dep[a]>dep[b] then
begin
t:=a;
a:=b;
b:=t;
end; if dep[a]<>dep[b] then
for i:=trunc(ln(dep[b]-dep[a])/ln())+ downto do
if dep[b]-<<i>=dep[a] then
begin
b:=fa[b,i];
ans:=ans+<<i;
end; if a<>b then
for i:=trunc(ln(dep[a])/ln())+ downto do
if fa[a,i]<>fa[b,i] then
begin
a:=fa[a,i];
b:=fa[b,i];
ans:=ans+<<(i+);
end; if a<>b then inc(ans,);
end; begin readln(n); if n= then
begin
writeln();
halt;
end; maketree; readln(m); read(t1);
for i:= to m do
begin
read(t2); lca(t1,t2);
t1:=t2;
end; writeln(ans); end.
LCA倍增算法的错误与模板的更多相关文章
- LCA倍增算法
LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 ...
- 最近公共祖先 LCA 倍增算法
树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 ...
- POJ 1330 Nearest Common Ancestors (LCA,倍增算法,在线算法)
/* *********************************************** Author :kuangbin Created Time :2013-9-5 9:45:17 F ...
- LCA 倍增算法模板
. #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm&g ...
- 算法笔记--lca倍增算法
算法笔记 模板: vector<int>g[N]; vector<int>edge[N]; ][N]; int deep[N]; int h[N]; void dfs(int ...
- LCA(最近公共祖先)之倍增算法
概述 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 如图,3和5的最近公共祖先是1,5和2的最近公共祖先是4 在本篇中我们先介 ...
- LCA(倍增在线算法) codevs 2370 小机房的树
codevs 2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...
- Lca 之倍增算法
引入: 比如说要找树上任意两个点的路上的最大值.如果是一般的做法 会 接近o(n)的搜,从一个点搜到另一个点,但是如果询问多了复杂度就很高了. 然后我们会预处理.预处理是o(n²)的,询问是o(1)的 ...
- POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)
1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...
随机推荐
- 【Unity】改变向量的方向而不改变其大小
最近在做一个打砖块游戏时遇到一个小问题,就是小球有可能会在左右两个边界之间做循环往返运动而导致游戏无法继续进行下去,于是我打算让小球在垂直撞向边界时改变一下方向,但是速度不变,尝试了一些方法但是没有达 ...
- Android程序函数 将assets文件夹下的文件复制到手机的sd卡中(包括子文件夹)
最近在做个功能是将asset文件夹下的所有文件(包括子文件)全部拷贝出来到指定目录下.所用的方法无非是用AssetManager.但是这里 有个问题是也要讲子文件夹和子文件都要拷贝出来.到网上Goog ...
- @Value取不到值引出的spring的2种配置文件applicationContext.xml和xxx-servlet.xml
项目中经常会用到配置文件,定义成properties的形式比较常见,为了方便使用一般在spring配置文件中做如下配置: <context:property-placeholder ignore ...
- [转]NopCommerce How to code my own payment method
本文转自:http://docs.nopcommerce.com/display/nc/How+to+code+my+own+payment+method Payment methods are im ...
- [转]二重积分换元法的一种简单证明 (ps:里面的符号有点小错误,理解就好。。。
---恢复内容开始--- 10.3二重积分的换元积分法 在一元函数定积分的计算中,我们常常进行换元,以达删繁就简的目的,当然,二重积分也有换元积分的问题. 首先让我们回顾一下前面曾讨论的一个事实. 设 ...
- UVA 11582 Colossal Fibonacci Numbers!【数学】
大一刚开始接触ACM就买了<算法竞赛入门经典>这本书,当时只能看懂前几章,而且题目也没做,粗鄙地以为这本书不适合自己.等到现在快大三了再回过头来看,发现刘老师还是很棒的! 扯远了... 题 ...
- AC日记——石头剪刀布 openjudge 1.6 08
08:石头剪刀布 总时间限制: 1000ms 内存限制: 65536kB 描述 石头剪刀布是常见的猜拳游戏.石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一样,则不分胜负. 一天,小A和小B正好在 ...
- arr的高级用法
arr的高级用法 reduce 方法(升序) 语法: array1.reduce(callbackfn[, initialValue]) 参数 定义 array1 必需.一个数组对象. callbac ...
- OAuth2学习及DotNetOpenAuth部分源码研究
OAuth2学习及DotNetOpenAuth部分源码研究 在上篇文章中我研究了OpenId及DotNetOpenAuth的相关应用,这一篇继续研究OAuth2. 一.什么是OAuth2 OAuth是 ...
- JProfiler
1 前言 回答之前先让我们来看看什么是jProfiler:JProfiler是一个商业授权的Java剖析工具,由EJ技术有限公司,针对Java EE和Java SE应用程序开发的.它允许两个内存剖面 ...