算法笔记--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 ...
随机推荐
- Lower Power with CPF(一)
CPF(Common Power Format):cadence推出的一种在设计中描述低功耗设计的文件.完全按Tcl的语言格式来定义. CPF文件在整个前端后端的过程中,需要的部分不一样,所以CPF文 ...
- REST服务安全-双向认证
1. 创建服务器密钥,其密钥库为 d:/mykeys/server.ks,注意keypass和storepass保持一致,它们分别代表 密钥密码和密钥库密码,注意 CN=localhost 中,loc ...
- python 爬虫煎蛋网
import urllib.request import os from urllib import error import re import base64 def url_open(url): ...
- redis删除单个key和多个key,ssdb会落地导致重启redis无法清除缓存
redis删除单个key和多个key,ssdb会落地导致重启redis无法清除缓存,需要针对单个key进行删除 删除单个:del key 删除多个:redis-cli -a pass(密码) keys ...
- python+requests接口自动化测试
转自https://my.oschina.net/u/3041656/blog/820023 原来的web页面功能测试转变成接口测试,之前大多都是手工进行,利用postman和jmeter进行的接口测 ...
- 远程登录 dos命令
1.桌面连接命令 mstsc /v: 192.168.1.250 /console 2.若需要远程启动所有Internet服务,可以使用iisreset命令来实现. 进入“命令提示符”窗口.在提示符后 ...
- MHA集群(gtid复制)和vip漂移
在上一片博客中,讲述了怎么去配置MHA架构!这片博客不再细说,只说明其中MySQL主从搭建,这里使用的是gtid加上半同步复制! 步骤与上一片博客一样,不同之处在于MySQL主从的搭建!详细的gtid ...
- P1771 方程的解_NOI导刊2010提高(01)
P1771 方程的解_NOI导刊2010提高(01) 按题意用快速幂把$g(x)$求出来 发现这不就是个组合数入门题吗! $k$个人分$g(x)$个苹果,每人最少分$1$个,有几种方法? 根据插板法, ...
- C++面向对象高级开发课程(第一周)
0. 内存分区 计算机中的内存在用于编程时,被人为的进行了分区(Segment),分为: -“栈区”(Stack) -“堆区”(Heap) -全局区(静态 区,Static) -文字常量区和程序代码区 ...
- WordPress REST API 内容注入漏洞
1 WordPress REST API 内容注入漏洞 1.1 摘要 1.1.1 漏洞介绍 WordPress是一个以PHP和MySQL为平台的自由开源的博客软件和内容管理系统.在4.7.0版本后,R ...