1.tarjan求lca

思想:

void tarjan(int u,int f){

    for(int i=---){//枚举边
if(v==f) continue;
dfs(v); //继续搜
unionn(v);//合并
vis[v]=; //标记
}
for(int i){// 和u有关的询问
if(vis[v])
lca=find(v);
//若访问过,lca为find(v)
}
}

模板代码

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std; const int N=;
inline int read(){
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;}
int n,m,s,head[N],tot,fa[N];
struct node{int v,next;}e[N<<];
inline void insert(int u,int v){
e[++tot]=(node){v,head[u]};head[u]=tot;
e[++tot]=(node){u,head[v]};head[v]=tot;}
struct nodex{int x,y,lca;}q[N];
vector<int> link[N];bool vis[N];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline void unionn(int x,int y){
int xx=find(x),yy=find(y);
if(xx!=yy) fa[yy]=xx;}
inline void dfs(int u,int f){
for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(v==f) continue;
dfs(v,u);
unionn(u,v);
vis[v]=;
}
for(int i=;i<link[u].size();i++){
int v=link[u][i];
int k1=q[v].x,k2=q[v].y;
if(k1==u&&vis[k2]) q[v].lca=find(k2);
else if(k2==u&&vis[k1]) q[v].lca=find(k1);
}
}
int main(){
n=read(),m=read(),s=read();
rep(i,,n-){fa[i]=i;
int x=read(),y=read();insert(x,y);}
rep(i,,m){q[i].x=read(),q[i].y=read();
link[q[i].x].push_back(i);
link[q[i].y].push_back(i);}
fa[n]=n;dfs(s,);
rep(i,,m) printf("%d\n",q[i].lca); return ;
}

2.倍增lca(在线)

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std; const int N=;
inline int read(){
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;}
int n,m,s,ss,head[N],tot,dep[N],fa[N][],k;
struct node{int v,next;}e[N<<];
inline void insert(int u,int v){
e[++tot]=(node){v,head[u]};head[u]=tot;
e[++tot]=(node){u,head[v]};head[v]=tot;}
inline void dfs(int u){
dep[u]=dep[fa[u][]]+;
for(register int i=;i<=ss;i++)
fa[u][i]=fa[fa[u][i-]][i-]; for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(v==fa[u][]) continue;
fa[v][]=u;dfs(v);
}
}
int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
int k=dep[x]-dep[y]; for(register int i=ss;i>=;i--)
if(k&(<<i)) x=fa[x][i]; if(x==y) return x; for(register int i=ss;i>=;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i]; return fa[x][];}
int main(){
n=read(),m=read(),s=read(); ss=ceil(log2(n));
rep(i,,n-){
int x=read(),y=read();
insert(x,y);} fa[s][]=; dfs(s); rep(i,,m){
int a=read(),b=read();
printf("%d\n",lca(a,b));} return ;
}

类似模板 s=ceil(log2(n));  bzoj 1787紧急集合

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define dec(i,x,y) for(register int i=x;i>=y;i--)
#define ll long long
using namespace std;
const int N=;
inline int read(){
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;}
int fa[N][],head[N],tot,dep[N],s;
struct node{int v,next;}e[N<<];
void insert(int u,int v){
e[++tot]=(node){v,head[u]};head[u]=tot;
e[++tot]=(node){u,head[v]};head[v]=tot;}
int n,m,x,y,z;
void dfs(int u){
dep[u]=dep[fa[u][]]+;
for(int i=;i<=s;i++)
fa[u][i]=fa[fa[u][i-]][i-]; for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(v==fa[u][]) continue;
fa[v][]=u;dfs(v);}
}
int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
int k=dep[x]-dep[y]; for(int i=s;i>=;i--)
if(k&(<<i)) x=fa[x][i]; if(x==y) return x; for(int i=s;i>=;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i]; return fa[x][];}
int main(){
n=read();m=read();
s=ceil(log2(n));
rep(i,,n-){
x=read();y=read();insert(x,y);}
dfs();
rep(i,,m){
x=read();y=read();z=read();
int xx=lca(x,y),yy=lca(y,z),zz=lca(z,x);
if(xx==yy)printf("%d ",zz);
else if(xx==zz) printf("%d ",yy);
else if(yy==zz) printf("%d ",xx);
printf("%d\n",dep[x]+dep[y]+dep[z]-dep[xx]-dep[yy]-dep[zz]);}
return ;
}

3.树剖(在线)

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
using namespace std; const int N=;
inline int read(){
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+(ch^);ch=getchar();}
return x*f;}
int n,m,s,head[N],tot;
struct node{int v,next;}e[N<<];
inline void insert(int u,int v){
e[++tot]=(node){v,head[u]};head[u]=tot;
e[++tot]=(node){u,head[v]};head[v]=tot;} int son[N],fa[N],dep[N],siz[N],top[N]; inline void dfs1(int u ,int f){
fa[u]=f;siz[u]=;dep[u]=dep[f]+;
for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(v==f) continue;
dfs1(v,u);siz[u]+=siz[v];
if(siz[son[u]]<siz[v]) son[u]=v;
}
}
inline void dfs2(int u,int tp){
top[u]=tp;
if(!son[u]) return;
dfs2(son[u],tp);
for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(!top[v]) dfs2(v,v);}
}
int lca(int x,int y){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(dep[fx]<dep[fy]) swap(fx,fy),swap(x,y);
x=fa[fx],fx=top[x];}
return dep[x]<dep[y]?x:y;}
int main(){
n=read(),m=read(),s=read();
rep(i,,n-){
int x=read(),y=read();
insert(x,y);}
dfs1(s,);dfs2(s,s);
rep(i,,m){
int a=read(),b=read();
printf("%d\n",lca(a,b));}
return ;
}

tarjan,树剖,倍增求lca的更多相关文章

  1. 蓝书4.1-4.4 树状数组、RMQ问题、线段树、倍增求LCA

    这章的数据结构题很真实 T1 排队 bzoj 1699 题目大意: 求静态一些区间的最大值-最小值 思路: ST表裸题 #include<iostream> #include<cst ...

  2. 树链剖分与倍增求LCA

    树链剖分与倍增求\(LCA\) 首先我要吐槽机房的辣基供电情况,我之前写了一上午,马上就要完成的时候突然停电,然后\(GG\)成了送链剖分 其次,我没歧视\(tarjan LCA\) 1.倍增求\(L ...

  3. 树链剖分求LCA

    树链剖分中各种数组的作用: siz[]数组,用来保存以x为根的子树节点个数 top[]数组,用来保存当前节点的所在链的顶端节点 son[]数组,用来保存重儿子 dep[]数组,用来保存当前节点的深度 ...

  4. 【倍增】洛谷P3379 倍增求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  5. 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)

    洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...

  6. [学习笔记] 树上倍增求LCA

    倍增这种东西,听起来挺高级,其实功能还没有线段树强大.线段树支持修改.查询,而倍增却不能支持修改,但是代码比线段树简单得多,而且当倍增这种思想被应用到树上时,它的价值就跟坐火箭一样,噌噌噌地往上涨. ...

  7. 树上倍增求LCA(最近公共祖先)

    前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...

  8. [算法]树上倍增求LCA

    LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...

  9. hdu 2586 How far away ? 倍增求LCA

    倍增求LCA LCA函数返回(u,v)两点的最近公共祖先 #include <bits/stdc++.h> using namespace std; *; struct node { in ...

随机推荐

  1. DOM中表格的操作方法总结

    DOM中表格的操作方法总结 <table/>元素的方法如下: caption:指向<caption/>元素(如果存在): tBodies:<tbody/>元素的集合 ...

  2. mysql的主主复制详解

    Mysql双主部署 解释: 所谓双主备份,其实也就是互做主从复制,每台master既是master,又是另一台服务器的slave.这样,任何一方所做的变更,都会通过复制应用到另外一方的数据库中. 要求 ...

  3. [Java] Thread的start()和run()函数区别

    1.start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码: 通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状 ...

  4. HTML DOM 節點

    節點: 整個html文檔是文檔節點: 注釋為注釋節點: 文本為文本節點: html元素為元素節點: html包含的內容為html節點. 節點間的關係: 父節點,子節點和同胞節點. html節點為根節點 ...

  5. Django model 中的字段解释

    Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField:一个自动递增的整型字段,添加记录时它会自动增长.你通常不需 ...

  6. BZOJ3425[POI2013]Polarization——DP+bitset+分块

    题目描述 Everyone knew it would only be a matter of time. So what? Faced for years on, a peril becomes t ...

  7. BZOJ2223[Coci 2009]PATULJCI——主席树

    题目描述 输入  先输入一个数n,然后一个数表示这n个数中最大的是多少,接下来一行n个数.然后一个数m,最后m行询问每次两个数l,r. 输出 no或者yes+这个数 样例输入 10 3 1 2 1 2 ...

  8. Js 百分比进度条

    [构想] CSS3 + JS CSS3控制进度 利用CSS3中的 @keyframes JS实现百分比 根据CSS来调整,时间 [页面代码] 第一种: 默认直接进入就是下载 CSS代码 body { ...

  9. MT【231】棋子方法数

    设有5枚无区别的棋子放在如图$5*5$的棋盘的小方格中,放棋子的规则是每行每列放且仅放一个棋子,同时,不允许放在黑方格内,则共有______ 方法. 答案:5的错排数44.第一行的数不放第二列(相当于 ...

  10. 【LG 4831】Scarlet loves WenHuaKe(生成函数)

    题目链接 一道好题,第一次用生成函数做题.感谢赛珂狼教我这个做法. 首先我们显然可以把题目中的限制转化成一个二分图的模型:左边有$n$个点,右边有$m$个点,如果在棋盘$(i,j)$这个点上放了炮,那 ...