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 ...
随机推荐
- SQL Server 2008 R2——VC++ ADO 操作 重复利用_ParameterPtr
==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...
- 烂泥:使KVM显示VM的IP地址及主机名
本文由秀依林枫提供友情赞助,首发于烂泥行天下. KVM虚拟化学习已经有一段时间了,现在虚拟化软件比较多,对比了下目前使用比较多的VMware Vsphere.发现在不进入VM系统的情况下,Vspher ...
- 零拷贝传输(zero-copy transfer)——sendfile()
做Web服务器时通常需要将文件传送出去,其中一种方法是通过定义一个buffer每次读取文件发送给接收端.大多数服务器会选择sendfile的方式,nginx实现时就是采用这种方式.对于并发搞得服务器性 ...
- Fitbit Flex 智能手环佩戴心得 主要说说过敏
参杂一篇杂文. 也是因为体重飙升,所以去年下半年的时候入手了一个Fitbit flex. 当时相比Jawbone up,nfc和ble的特性,以及防水性还是更吸引我一点.所以就入手了. 佩带了如此长的 ...
- NYOJ-取石子(六)
取石子(六) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 最近TopCoder的PIAOYI和HRDV很无聊,于是就想了一个游戏,游戏是这样的:有n堆石子,两个人轮流 ...
- codevs哈希水题
1230 多重hash练习一下,不用也可以 // // main.cpp // codeves1230 // // Created by Candy on 9/29/16. // Copyright ...
- Mecanim分析
前言 目前我还只是学习到Mecanima的初级阶段,看完了阿赵的日志<Unity3D 4.0新功能:Mecanim动画系统基础教程>,对Mecanima的了解更深入了一些,谢谢他的分享. ...
- [转]MVC整合Ajax
MVC教程第五篇:MVC整合Ajax 2010-02-01 作者:张洋 来源:张洋的BLOG 摘要 本文将从完成“输入数据验证”这个功能出发,逐渐展开ASP.NET MVC与Ajax结合的方法 ...
- 深入C#数据类型
一:值类型与引用类型 值类型源于System.ValueType家族,值类型包括基本数据类型,结构类型和枚举类型. 值类型:在栈上储存的真实的值. 引用类型源于System.Object家族,在C#中 ...
- 后缀自动机&序列自动机综合
好像序列自动机还没有写过- 串长为n的串共有n+1个节点,除了串中的n个节点,还有一个空的根节点放在串首.每个节点至多有26条出边,每条边连向它之后的第一个字符. 串中的任意一个子序列对应了一条根到某 ...