补了一发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树上倍增算法】的更多相关文章

  1. Codevs 2370 小机房的树 LCA 树上倍增

    题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子, ...

  2. LCA的倍增算法

    LCA,即树上两点之间的公共祖先,求这样一个公共祖先有很多种方法: 暴力向上:O(n) 每次将深度大的点往上移动,直至二者相遇 树剖:O(logn) 在O(2n)预处理重链之后,每次就将深度大的沿重链 ...

  3. LCA树上倍增求法

    1.LCA LCA就是最近公共祖先(Least common ancestor),x,y的LCA记为z=LCA(x,y),满足z是x,y的公共祖先中深度最大的那一个(即离他们最近的那一个)qwq 2. ...

  4. LCA——树上倍增

    首先,什么是LCA? LCA:最近公共祖先 祖先:从当前点到根节点所经过的点,包括他自己,都是这个点的祖先 A和B的公共祖先:同时是A,B两点的祖先的点 A和B的最近公共祖先:深度最大的A和B的公共祖 ...

  5. HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822 Problem Description Three countries, Red, Yellow ...

  6. LCA树上倍增

    LCA就是最近公共祖先,比如 节点10和11的LCA就是8,9和3的LCA就是3. 我们这里讲一下用树上倍增来求LCA. 大家都可以写出暴力解法,两个节点依次一步一步往上爬,直到爬到了相同的一个节点. ...

  7. BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增

    题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...

  8. Lca 之倍增算法

    引入: 比如说要找树上任意两个点的路上的最大值.如果是一般的做法 会 接近o(n)的搜,从一个点搜到另一个点,但是如果询问多了复杂度就很高了. 然后我们会预处理.预处理是o(n²)的,询问是o(1)的 ...

  9. Codeforces 191C (LCA+树上差分算法)

    题面 传送门 题目大意: 给出一棵树,再给出k条树上的简单路径,求每条边被不同的路径覆盖了多少次 分析 解决这个问题的经典做法是树上差分算法 它的思想是把"区间"修改转化为左右端点 ...

随机推荐

  1. 【shell】文本处理的一些小技巧

    一.Shell 二.Sed 三.Awk

  2. 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 ...

  3. 【二分贪心+精度问题】F. Pie

    https://www.bnuoj.com/v3/contest_show.php?cid=9154#problem/F [题意] 给定n个已知半径的披萨,有m个人要分这n个披萨 要求每个人分到的面积 ...

  4. 单源最短路径 Bellman_ford 和 dijkstra

    首先两个算法都是常用于 求单源最短路径 关键部分就在于松弛操作 实际上就是dp的感觉 if (dist[e.to] > dist[v] + e.cost) { dist[e.to] = dist ...

  5. java容器详解(以Array Arrays ArrayList为例)

    //先记录一个想法……java实在是太臃肿了,纯面向对象也有不少弊端…… //能不能把java精简一下啊! 先上结论: Array:认真看api索引的话,Array有两个.一个是sql中的接口,一个是 ...

  6. angularjs ngRoute的使用简单例子

    很丑的小例子,刚学angularjs,写下来方面以后看. 1.例子的工程目录如下: 2.index.html代码如下: <!DOCTYPE html><html><hea ...

  7. php之ThinkPHP的memcached类的修改

    php之ThinkPHP的memcached类的修改 在Think\Cache\Driver\Memcached.class.php中,增加方法获取错误信息的方法,方便调试, public funct ...

  8. POJ3177,/3352.求最少添加多少边使无向图边双连通

    俩个题一样.tarjan算法应用,开始求桥,WA,同一个边双连通分量中low值未必都相同,不能用此来缩点.后来用并查集来判断,若不是桥,则在一个双连通分量中,并之,后边再查,将同一个双连通分量中的点通 ...

  9. Linux审计sudo

    Linux日志审计项目案例实战(生产环境日志审计项目解决方案) https://www.linuxidc.com/Linux/2015-07/120501.htm

  10. HDU——1054 Strategic Game

    Strategic Game Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...