算法笔记--lca倍增算法
算法笔记
模板:
vector<int>g[N];
vector<int>edge[N];
int anc[][N];
int deep[N];
int h[N];
void dfs(int o,int u,int w)
{
if(u!=o)deep[u]=deep[o]+,h[u]=h[o]+w;
for(int j=;j<g[u].size();j++)
{
if(g[u][j]!=o)
{
anc[][g[u][j]]=u;
for(int i=;i<;i++)anc[i][g[u][j]]=anc[i-][anc[i-][g[u][j]]];
dfs(u,g[u][j],edge[u][j]);
}
}
}
int lca(int u,int v)
{
if(deep[u]<deep[v])swap(u,v);
for(int i=;i>=;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
if(u==v)return u;
for(int i=;i>=;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
return anc[][u];
}
int dis(int u,int v)
{
int l=lca(u,v);
return h[u]+h[v]-*h[l];
}
例题:
带权lca
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int INF=0x3f3f3f3f;
const int N=5e4+;
vector<int>g[N];
vector<int>edge[N];
int anc[][N];
int deep[N];
int h[N];
void dfs(int o,int u,int w)
{
if(u!=o)deep[u]=deep[o]+,h[u]=h[o]+w;
for(int j=;j<g[u].size();j++)
{
if(g[u][j]!=o)
{
anc[][g[u][j]]=u;
for(int i=;i<;i++)anc[i][g[u][j]]=anc[i-][anc[i-][g[u][j]]];
dfs(u,g[u][j],edge[u][j]);
}
}
}
int lca(int u,int v)
{
if(deep[u]<deep[v])swap(u,v);
for(int i=;i>=;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
if(u==v)return u;
for(int i=;i>=;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
return anc[][u];
}
int dis(int u,int v)
{
int l=lca(u,v);
return h[u]+h[v]-*h[l];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
int n,u,v,c,m;
cin>>n;
for(int i=;i<n-;i++)
{
cin>>u>>v>>c;
g[u].push_back(v);
g[v].push_back(u);
edge[u].push_back(c);
edge[v].push_back(c);
}
cin>>m;
for(int i=;i<;i++)anc[i][]=;
dfs(,,);
while(m--)
{
cin>>u>>v;
cout<<dis(u,v)<<endl;
}
return ;
}
普通lca
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls rt<<1,l,m
#define rs rt<<1|1,m+1,r
const int INF=0x3f3f3f3f;
const int N=1e5+;
vector<int>g[N];
int anc[][N];
int deep[N];
void dfs(int o,int u)
{
if(o!=u)deep[u]=deep[o]+;
for(int j=;j<g[u].size();j++)
{
if(o!=g[u][j])
{
anc[][g[u][j]]=u;
for(int i=;i<;i++)anc[i][g[u][j]]=anc[i-][anc[i-][g[u][j]]];
dfs(u,g[u][j]);
}
}
}
int lca(int u,int v)
{
if(deep[u]<deep[v])swap(u,v);
for(int i=;i>=;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
if(u==v)return u;
for(int i=;i>=;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
return anc[][u];
}
int dis(int u,int v)
{
return deep[u]+deep[v]-*deep[lca(u,v)];
}
void init()
{
for(int i=;i<;i++)anc[][]=;
dfs(,);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
int n,m;
cin>>n;
for(int i=;i<n;i++)
{
int a,b;
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
init();
cin>>m;
int a,b,ans=;
cin>>a;
for(int i=;i<m;i++)
{
cin>>b;
ans+=dis(a,b);
a=b;
}
cout<<ans<<endl;
return ;
}
带权lca,当lca(a,b)==a时,韵韵才能参加。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls rt<<1,l,m
#define rs rt<<1|1,m+1,r
#define pb push_back
const int INF=0x3f3f3f3f;
const int N=1e4+;
vector<int>g[N];
vector<ll>edge[N];
int anc[][N];
int deep[N];
ll h[N];
bool vis[N]={false};
int s;
void dfs(int o,int u,ll w)
{
if(o!=u)deep[u]=deep[o]+,h[u]=h[o]+w;
for(int j=;j<g[u].size();j++)
{
if(g[u][j]!=o)
{
anc[][g[u][j]]=u;
for(int i=;i<;i++)anc[i][g[u][j]]=anc[i-][anc[i-][g[u][j]]];
dfs(u,g[u][j],edge[u][j]);
}
}
}
int lca(int u,int v)
{
if(deep[u]<deep[v])swap(u,v);
for(int i=;i>=;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
if(u==v)return u;
for(int i=;i>=;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
return anc[][u];
}
ll dis(int u,int v)
{
return h[u]+h[v]-*h[lca(u,v)];
}
void init()
{
for(int i=;i<;i++)anc[i][]=;
dfs(,,);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
int n,m,a,b;
ll t;
cin>>n>>m;
for(int i=;i<n;i++)
{
cin>>a>>b>>t;
g[a].pb(b);
g[b].pb(a);
edge[a].pb(t);
edge[b].pb(t);
}
init();
int cnt=;
ll ans=;
for(int i=;i<m;i++)
{
int a,b;
cin>>a>>b;
if(lca(a,b)==a)
{
cnt++;
ans+=h[b]-h[a];
}
}
cout<<cnt<<endl;
cout<<ans<<endl;
return ;
}
带权lca
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
const int INF=0x3f3f3f3f;
const int N=4e4+;
vector<int>g[N];
vector<int>edge[N];
int deep[N];
int h[N];
int anc[][N];
bool vis[N]={false};
int s=;
void dfs(int o,int u,int w)
{
deep[u]=deep[o]+;
h[u]=h[o]+w;
for(int j=;j<g[u].size();j++)
{
if(g[u][j]!=o)
{
anc[][g[u][j]]=u;
for(int i=;i<;i++)anc[i][g[u][j]]=anc[i-][anc[i-][g[u][j]]];
dfs(u,g[u][j],edge[u][j]);
}
}
}
int lca(int u,int v)
{
if(deep[u]<deep[v])swap(u,v);
for(int i=;i>=;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
if(u==v)return u;
for(int i=;i>=;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
return anc[][u];
}
ll dis(int u,int v)
{
return h[u]+h[v]-*h[lca(u,v)];
}
void init()
{
for(int i=;i<;i++)anc[i][]=;
dfs(,,);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
int t;
cin>>t;
while(t--)
{
int n,m,a,b,k;
cin>>n>>m;
for(int i=;i<n;i++)
{
cin>>a>>b>>k;
g[a].pb(b);
g[b].pb(a);
edge[a].pb(k);
edge[b].pb(k);
vis[b]=true;
}
init();
for(int i=;i<m;i++)
{
cin>>a>>b;
cout<<dis(a,b)<<endl;
}
//cout<<endl;
}
return ;
}
带权lca,三点之间的最短路径公式h[a]+h[b]+h[c]-h[lca(a,b)]-h[lca(a,c)]-h[lca(b,c)]。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
const int INF=0x3f3f3f3f;
const int N=5e4+;
vector<int>g[N];
vector<int>edge[N];
int deep[N];
int h[N];
int anc[][N];
void dfs(int o,int u,int w)
{
if(u!=o)deep[u]=deep[o]+,h[u]=h[o]+w;
for(int j=;j<g[u].size();j++)
{
if(g[u][j]!=o)
{
anc[][g[u][j]]=u;
for(int i=;i<;i++)anc[i][g[u][j]]=anc[i-][anc[i-][g[u][j]]];
dfs(u,g[u][j],edge[u][j]);
}
}
}
int lca(int u,int v)
{
if(deep[u]<deep[v])swap(u,v);
for(int i=;i>=;i--)if(deep[anc[i][u]]>=deep[v])u=anc[i][u];
if(u==v)return u;
for(int i=;i>=;i--)if(anc[i][u]!=anc[i][v])u=anc[i][u],v=anc[i][v];
return anc[][u];
}
int dis(int u,int v)
{
return h[u]+h[v]-*h[lca(u,v)];
}
void init()
{
for(int i=;i<;i++)anc[i][]=;
dfs(,,);
}
int main()
{
int n,q,a,b,c;
bool flag=true;
while(~scanf("%d",&n)&&n)
{
if(flag) flag=false;
else printf("\n");
for(int i=;i<n;i++)g[i].clear(),edge[i].clear();
for(int i=;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
g[a].pb(b);
g[b].pb(a);
edge[a].pb(c);
edge[b].pb(c);
}
init();
scanf("%d",&q);
while(q--)
{
scanf("%d%d%d",&a,&b,&c);
printf("%d\n",h[a]+h[b]+h[c]-h[lca(a,b)]-h[lca(a,c)]-h[lca(b,c)]);
}
}
return ;
}
算法笔记--lca倍增算法的更多相关文章
- LCA倍增算法
LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 ...
- 算法笔记_071:SPFA算法简单介绍(Java)
目录 1 问题描述 2 解决方案 2.1 具体编码 1 问题描述 何为spfa(Shortest Path Faster Algorithm)算法? spfa算法功能:给定一个加权连通图,选取一个 ...
- 算法笔记之KMP算法
本文是<算法笔记>KMP算法章节的阅读笔记,文中主要内容来源于<算法笔记>.本文主要介绍了next数组.KMP算法及其应用以及对KMP算法的优化. KMP算法主要用于解决字符串 ...
- 最近公共祖先 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 ...
- 算法笔记_066:Kruskal算法详解(Java)
目录 1 问题描述 2 解决方案 2.1 构造最小生成树示例 2.2 伪码及时间效率分析 2.3 具体编码(最佳时间效率) 1 问题描述 何为Kruskal算法? 该算法功能:求取加权连通图的最小 ...
- 算法笔记_054:Prim算法(Java)
目录 1 问题描述 2 解决方案 2.1 贪心法 1 问题描述 何为Prim算法? 此处引用网友博客中一段介绍(PS:个人感觉网友的这篇博客对于Prim算法讲解的很清楚,本文与之相区别的地方在于具 ...
- LCA倍增算法的错误与模板
先上我原来的错误的代码 type node=^link; link=record num:int64; next:node; end; var fa:..,..] of int64; dep:..] ...
- LCA 倍增算法模板
. #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm&g ...
随机推荐
- Twitter OA prepare: Anagram is A Palindrome
Algorithm: Count the number of occurrence of each character. Only one character with odd occurrence ...
- TensorFlow 开发环境搭建--Pycharm
今天动手开始搭建TensorFlow开发环境, 用PyCharm来跑MNIST中的例子.记录过程如下 下载安装 (1)首先安装AnaConda, AnaConda可以帮忙去管理安装包,帮忙创建虚拟环境 ...
- JSP—作用域
application: 用于同一个应用内,所有用户之间的数据共享 作用域: request作用域: 在页面转发,包含中同样有效. <% pageContext.include("te ...
- 20154312 曾林 Exp3 免杀原理与实践
20154312 曾林 0.写在前面 AV厂商检测恶意软件的方式主流的就三种: 基于特征码的检测 启发式恶意软件检测 基于行为的恶意软件检测 我们要做的就是让我们的恶意软件没法被这三种方式找到,也就是 ...
- OS X 下动态库的引用
foo.c #include <stdio.h> void foo(void) { printf("foo.\n"); } main.c #include <st ...
- python 不同集合上元素的迭代 chain()
itertools.chain()可以接受一个可迭代对象列表作为输入,并返回一个迭代器,有效的屏蔽掉在多个容器中迭代细节 >>> from itertools import chai ...
- Jmeter响应内容显示乱码问题的解决办法
Jmeter在访问接口的时候,响应内容如果有中文可能会显示乱码,原因应该是响应页面没有做编码处理,jmeter默认按照ISO-8859-1编码格式进行解析. 下面把解决步骤列一下: 现象:jmeter ...
- (六)最最基本的git操作
1.git init——初始化仓库 初始化成功的标志如下(.git默认为隐藏) 2.git status——查看仓库状态 ps:未跟踪的文件 (untracked files) 不妨在尝试在仓库建立一 ...
- 深入浅出JVM
这篇文章简要解析了JVM的内部结构.下面这幅图展示了一个典型的JVM(符合JVM Specification Java SE 7 Edition)所具备的关键内部组件. 上图展示的所有这些组件都将在下 ...
- Python3 Selenium自动化测试赋值出现:WebDriverException: Message: unknown error: call function result missing 'value'
Python3 Selenium自动化测试赋值出现:WebDriverException: Message: unknown error: call function result missing ' ...