方法1:倍增

1498ms

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=5e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,q,root,a,b;
struct edge{
int v,ne;
}e[N<<];
int cnt=,h[N];
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
int fa[N][],deep[N],vis[N];
void dfs(int u){
vis[u]=;
for(int j=;(<<j)<=deep[u];j++)
fa[u][j]=fa[fa[u][j-]][j-];
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(vis[v]) continue;
deep[v]=deep[u]+;
fa[v][]=u;
dfs(v);
}
}
int lca(int x,int y){
if(deep[x]<deep[y]) swap(x,y);
int bin=deep[x]-deep[y];
for(int i=;i<=;i++)
if((<<i)&bin) x=fa[x][i];//,printf("x %d\n",i); for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
if(x==y) return x;
else return fa[x][];
}
int main(int argc, const char * argv[]) {
n=read();q=read();root=read();
for(int i=;i<=n-;i++) a=read(),b=read(),ins(a,b);
dfs(root);
for(int i=;i<=q;i++){
a=read();b=read();
printf("%d\n",lca(a,b));
}
return ;
}

方法2:树链剖分

1314ms

让链首深度大的走到重链的父节点直到在一条重链上,返回深度小的节点

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=5e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,q,root,a,b;
struct edge{
int v,ne;
}e[N<<];
int cnt=,h[N];
inline void ins(int u,int v){
cnt++;
e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
}
int fa[N],deep[N],mx[N],size[N];
void dfs(int u){
size[u]++;
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(v==fa[u]) continue;
fa[v]=u;deep[v]=deep[u]+;
dfs(v);
size[u]+=size[v];
if(size[v]>size[mx[u]]) mx[u]=v;
}
}
int tid[N],top[N],tot;
void dfs(int u,int anc){
if(!u) return;
tid[u]=++tot;top[u]=anc;
dfs(mx[u],anc);
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(v!=fa[u]&&v!=mx[u]) dfs(v,v);
}
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
return x;
}
int main(int argc, const char * argv[]) {
n=read();q=read();root=read();
for(int i=;i<=n-;i++) a=read(),b=read(),ins(a,b);
dfs(root);
dfs(root,root);
for(int i=;i<=q;i++){
a=read();b=read();
printf("%d\n",lca(a,b));
}
return ;
}

LCA 倍增||树链剖分的更多相关文章

  1. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  2. 洛谷P4180 [BJWC2010]次小生成树(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  3. 【BZOJ3626】LCA(树链剖分,Link-Cut Tree)

    [BZOJ3626]LCA(树链剖分,Link-Cut Tree) 题面 Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. ...

  4. 培训补坑(day8:树上倍增+树链剖分)

    补坑补坑.. 其实挺不理解孙爷为什么把这两个东西放在一起讲..当时我学这一块数据结构都学了一周左右吧(超虚的) 也许孙爷以为我们是省队集训班... 好吧,虽然如此,我还是会认真写博客(保证初学者不会出 ...

  5. uva 12655 Trucks [LCA](树链剖分+MST)

    The Subtle Balloons Company (SBC) is the main balloon provider for programming contests; it hashuge ...

  6. CF 191C Fools and Roads lca 或者 树链剖分

    They say that Berland has exactly two problems, fools and roads. Besides, Berland has n cities, popu ...

  7. 从lca到树链剖分 bestcoder round#45 1003

    bestcoder round#45 1003 题,给定两个点,要我们求这两个点的树上路径所经过的点的权值是否出现过奇数次.如果是一般人,那么就是用lca求树上路径,然后判断是否出现过奇数次(用异或) ...

  8. P3379 【模板】最近公共祖先(LCA)(树链剖分)版

    #include <bits/stdc++.h> #define read read() #define up(i,l,r) for(register int i = (l);i < ...

  9. 2018.09.16 bzoj3626: [LNOI2014]LCA(树链剖分)

    传送门 树链剖分好题. 对于每个点维护一个值vi" role="presentation" style="position: relative;"&g ...

随机推荐

  1. SQL Server 数据库分离与附加

    一.概述 SQL Server提供了“分离/附加”数据库.“备份/还原”数据库.复制数据库等多种数据库的备份和恢复方法.这里介绍一种学习中常用的“分离/附加”方法,类似于大家熟悉的“文件拷贝”方法,即 ...

  2. 基于CkEditor实现.net在线开发之路(4)快速布局,工具箱,模板载入,tab选项卡简单说明与使用

    上一章给常用的from表单控件属性页面,进行了简单说明和介绍,但是由于是在网页中做界面设计,操作肯定没有桌面应用程序方便,便捷,为了更方便的布局与设计,今天我主要说一下快速布局,工具箱,tab选项卡, ...

  3. 【工匠大道】Git的使用总结

    初衷是想将一些常用的代码整理在博客园上,但是考虑到博客园上的代码量多,需要折叠,折叠后就不能直接修改,于是想到了 大家都常用的 gitHub来进行代码的管理. 其实之前我是用过 Osa的git的,但是 ...

  4. Lind.DDD.IoC(大叔推荐)~在服务定位器中引入IoC容器~容器的适配器

    回到目录 关于依赖倒置(DIP) 高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口,通俗的讲,就是高层模块定义接口,低层模块负责实现,这在我们实际开发中经常被用到,层与层之间引用,经 ...

  5. linux下tomcat自启动设置

    1.进入/etc/init.d 2.新建文件tomcat,内容如下: #!/bin/sh # chkconfig: 345 99 10 # description: Auto-starts tomca ...

  6. javascript中DOM部分基础知识总结

    1.DOM介绍      1.1 DOM概念      文档对象模型(Document Object Model),它定义了访问和处理HTML文档的标准方法.现在我们主要接触到的是HTML DOM. ...

  7. c#的那些有效性判断

    在开发中合理的对象有效性判断是程序健壮性的重要保障,也有利于提高程序的执行效率.本人简单总结了几个需要判断对象是否为空的例子,分享如下: 一.集合对象中可以包含空对象,遍历集合对象时要同时判断集合中的 ...

  8. css水平垂直居中(绝对定位居中)

    使用绝对定位有个限制就是父集必须设置一个固定的高度. 首先HTML <div id="box"> <div class="child"> ...

  9. SharePoint 2013 搭建app本地开发环境

    使用SharePoint App,如果要通过应用程序目录分发 SharePoint 相关应用程序,如具有完全控制权限的 SharePoint 相关应用程序(无法部署到 Office 365 网站),则 ...

  10. 在Autodesk应用程序商店发布基于浏览器的Web应用程序

    你一定已经听说过Autodesk应用程序商店了,通过Autodesk应用程序商店,你可以免费下载或购买来自全球的优秀开发者发布的应用程序,来帮助你更快更方便的完成你的工作.而且作为开发者,您也可以在A ...