关于树论【LCA树上倍增算法】
补了一发LCA,表示这东西表面上好像简单,但是细节真挺多。
我学的是树上倍增,倍增思想很有趣~~(爸爸的爸爸叫奶奶.偶不,爷爷)有一个跟st表非常类似的东西,f[i][j]表示j的第2^i的祖先,就是说f[0][x]是父亲,f[1][x]是爷爷,f[2][x]是高祖父(爷爷的爷爷),f[3][x]是远祖父(高祖父的高祖父)
搞个事:
按古制辈份分为:自己,父亲、祖父、曾祖、高祖、天祖、烈祖、太祖、远祖、鼻祖。
扯回来,这个就是倍增的思想,可以方便的实现O(logn)的LCA,现在让你在构图的时候搞好f数组,一点问题都没有了吧~
然后怎么求LCA?首先,我们先让深度比较深的点往上跳,然后两个一起跳,直到跳到父亲相同。那我们跳的时候,就像二进制一样,可以一次跳2^i次方
caioj1236:(赤裸裸的LCA)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int x,y,next;
}a[];int len,last[];
void ins(int x,int y)
{
a[++len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
//f[i][j]表示j的第2^i的祖先
int Bin[],dep[],f[][];
void dfs(int x,int fa)//构树
{
f[][x]=fa;//x的2^0=1就是自己父亲
for(int i=;Bin[i]<=dep[x];i++)f[i][x]=f[i-][f[i-][x]];//倍增,爸爸的爸爸是爷爷
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa)
{
dep[y]=dep[x]+;
dfs(y,x);
}
}
}
int LCA(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);//让比较深的先往上跳
for(int i=;i>=;i--)//倒着,想象成二进制,比如要找第5个祖先,就变成101,从左往右把所有为一的跳一下
if(dep[x]-dep[y]>=Bin[i])x=f[i][x];
if(x==y)return x;
for(int i=;i>=;i--)//深度一样了,x和y一起跳
if(dep[x]>=Bin[i]&&f[i][x]!=f[i][y]){x=f[i][x];y=f[i][y];}
return f[][x];
}
int main()
{
Bin[]=;for(int i=;i<=;i++)Bin[i]=Bin[i-]*;
int n,m,x,y;
scanf("%d%d",&n,&m);
len=;memset(last,,sizeof(last));
for(int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
}
dep[]=;dfs(,);
while(m--)
{
scanf("%d%d",&x,&y);
printf("%d\n",LCA(x,y));
}
return ;
}
关于树论【LCA树上倍增算法】的更多相关文章
- Codevs 2370 小机房的树 LCA 树上倍增
题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子, ...
- LCA的倍增算法
LCA,即树上两点之间的公共祖先,求这样一个公共祖先有很多种方法: 暴力向上:O(n) 每次将深度大的点往上移动,直至二者相遇 树剖:O(logn) 在O(2n)预处理重链之后,每次就将深度大的沿重链 ...
- LCA树上倍增求法
1.LCA LCA就是最近公共祖先(Least common ancestor),x,y的LCA记为z=LCA(x,y),满足z是x,y的公共祖先中深度最大的那一个(即离他们最近的那一个)qwq 2. ...
- LCA——树上倍增
首先,什么是LCA? LCA:最近公共祖先 祖先:从当前点到根节点所经过的点,包括他自己,都是这个点的祖先 A和B的公共祖先:同时是A,B两点的祖先的点 A和B的最近公共祖先:深度最大的A和B的公共祖 ...
- HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822 Problem Description Three countries, Red, Yellow ...
- LCA树上倍增
LCA就是最近公共祖先,比如 节点10和11的LCA就是8,9和3的LCA就是3. 我们这里讲一下用树上倍增来求LCA. 大家都可以写出暴力解法,两个节点依次一步一步往上爬,直到爬到了相同的一个节点. ...
- BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增
题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...
- Lca 之倍增算法
引入: 比如说要找树上任意两个点的路上的最大值.如果是一般的做法 会 接近o(n)的搜,从一个点搜到另一个点,但是如果询问多了复杂度就很高了. 然后我们会预处理.预处理是o(n²)的,询问是o(1)的 ...
- Codeforces 191C (LCA+树上差分算法)
题面 传送门 题目大意: 给出一棵树,再给出k条树上的简单路径,求每条边被不同的路径覆盖了多少次 分析 解决这个问题的经典做法是树上差分算法 它的思想是把"区间"修改转化为左右端点 ...
随机推荐
- 【shell】文本处理的一些小技巧
一.Shell 二.Sed 三.Awk
- Codeforces Round #321 (Div. 2)-A. Kefa and First Steps,暴力水过~~
A. Kefa and First Steps time limit per test 2 seconds memory limit per test 256 megabytes input stan ...
- 【二分贪心+精度问题】F. Pie
https://www.bnuoj.com/v3/contest_show.php?cid=9154#problem/F [题意] 给定n个已知半径的披萨,有m个人要分这n个披萨 要求每个人分到的面积 ...
- 单源最短路径 Bellman_ford 和 dijkstra
首先两个算法都是常用于 求单源最短路径 关键部分就在于松弛操作 实际上就是dp的感觉 if (dist[e.to] > dist[v] + e.cost) { dist[e.to] = dist ...
- java容器详解(以Array Arrays ArrayList为例)
//先记录一个想法……java实在是太臃肿了,纯面向对象也有不少弊端…… //能不能把java精简一下啊! 先上结论: Array:认真看api索引的话,Array有两个.一个是sql中的接口,一个是 ...
- angularjs ngRoute的使用简单例子
很丑的小例子,刚学angularjs,写下来方面以后看. 1.例子的工程目录如下: 2.index.html代码如下: <!DOCTYPE html><html><hea ...
- php之ThinkPHP的memcached类的修改
php之ThinkPHP的memcached类的修改 在Think\Cache\Driver\Memcached.class.php中,增加方法获取错误信息的方法,方便调试, public funct ...
- POJ3177,/3352.求最少添加多少边使无向图边双连通
俩个题一样.tarjan算法应用,开始求桥,WA,同一个边双连通分量中low值未必都相同,不能用此来缩点.后来用并查集来判断,若不是桥,则在一个双连通分量中,并之,后边再查,将同一个双连通分量中的点通 ...
- Linux审计sudo
Linux日志审计项目案例实战(生产环境日志审计项目解决方案) https://www.linuxidc.com/Linux/2015-07/120501.htm
- HDU——1054 Strategic Game
Strategic Game Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...