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 ...
随机推荐
- strlen和sizeof的区别
1.sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型.该类型保证能容纳实现所建立的最大对象的字节大小. 2.sizeof是算符,strlen是函 ...
- vs2008环境nmake编译 apache 2.2.29 openssl 1.0.1g mod_ssl 不知道如何生成“"..\..\srclib\openssl\inc32\openssl\store.h"”
问题: vs2008环境nmake编译 apache 2.2.29 openssl 1.0.1g mod_ssl 不知道如何生成“"..\..\srclib\openssl\inc32\op ...
- C语言出错问题汇总【需要更新】
'getch' : undeclared identifier解决方案 在VC++6.0中编译程序 #include<stdio.h> void main() { printf(&qu ...
- 大话设计模式C++版——工厂方法模式
工厂方法模式是以简单工厂模式为基础的,如果未了解简单工厂模式的同学可先浏览<大话设计模式C++版——简单工厂模式>.在简单工厂模式中,提到过简单工厂模式的缺陷,即违背了开发—封闭原则,其主 ...
- Eclipse调试Bug的七种常用技巧
1. 条件断点 断点大家都比较熟悉,在Eclipse Java 编辑区的行头双击就会得到一个断点,代码会运行到此处时停止. 条件断点,顾名思义就是一个有一定条件的断点,只有满足了用户设置的条件,代码才 ...
- 给IIS添加CA证书以支持https
一.在IIS中生成Certificate Signing Request (CSR) 个人理解:生成CSR就是生成“私钥/公钥对”之后从中提取出公钥. 1. 打开IIS Manager,在根节点中选择 ...
- AC日记——逆波兰表达式 openjudge 3.3 1696
1696:逆波兰表达式 总时间限制: 1000ms 内存限制: 65536kB 描述 逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式 ...
- AC日记——紧急措施 openjudge 1.7 22
22:紧急措施 总时间限制: 1000ms 内存限制: 65536kB 描述 近日,一些热门网站遭受黑客入侵,这些网站的账号.密码及email的数据惨遭泄露.你在这些网站上注册若干账号(使用的用户 ...
- for循环与for循环嵌套
今天温习了下分支语句跟for循环,主要讲解了for循环嵌套,这里开始有点迷糊了,整理下思路在做练习 for循环嵌套用我自己的大白话来说就是一个外圈的for程序里面一个套着一个小的for程序,如果在范围 ...
- IntelliJ IDEA运行tomcat项目编码错误, 及如何指定tomcat编码
刚开始用IDEA, 在跑dubbo开发时, 发现一个很奇怪的问题, 远程调用服务端的方法时, 传入的中文参数会变成GBK编码. 经过好长时间的跟踪终于把问题定位到了IDEA里配置的Tomcat. 凡是 ...