树剖求LCA模板

  • O(logn)(n<=10^6)
  • https://www.cnblogs.com/cangT-Tlan/p/8846408.html
  • 把一棵树分成几条链,用数据结构去维护每一条链
  •  1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define rll register ll
     4 #define M 0x3f3f3f
     5 #define For(i,l,r) for(int i=l;i<=r;i++)
     6 using namespace std;
     7 ll n,m,s,head[M],a[M],x,y,z,tot,k,t;
     8 ll fa[M],d[M],top[M],size[M],id[M],ril[M];
     9 struct node1{
    10     ll to,nxt;
    11 }e[M<<1];
    12 struct node2{
    13     ll l,r,sum,flag;
    14 }tree[M<<1];
    15
    16 inline ll read(){
    17     ll f=1,sum=0;
    18     char ch=getchar();
    19     while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    20     while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
    21     return f*sum;
    22 }
    23
    24 inline void add(ll x,ll y){
    25     e[++tot].to=y;
    26     e[tot].nxt=head[x];
    27     head[x]=tot;
    28 }
    29
    30 inline void dfs1(ll u){//第一遍dfs遍历树,预处理d深度,size此点子节点个数,fa其父节点
    31     d[u]=d[fa[u]]+1;
    32     size[u]=1;
    33     for(rll i=head[u];i;i=e[i].nxt){
    34         if(e[i].to!=fa[u]){
    35             fa[e[i].to]=u;
    36             dfs1(e[i].to);
    37             size[u]+=size[e[i].to];
    38         }
    39     }
    40 }
    41
    42 inline void dfs2(ll u){//按照子节点个数多少划分轻重边,保证一个点只在一条链中。一般只用重边,轻边用不到。
    43     ll t=0;//top即为此点所在重边的顶点
    44     if(!top[u]) top[u]=u;
    45     for(rll i=head[u];i;i=e[i].nxt){
    46         if(e[i].to!=fa[u]&&size[e[i].to]>t) t=e[i].to;
    47     }
    48     if(t){
    49         top[t]=top[u];
    50         dfs2(t);
    51     }
    52     for(rll i=head[u];i;i=e[i].nxt){
    53         if(e[i].to!=fa[u]&&e[i].to!=t) dfs2(e[i].to);
    54     }
    55 }
    56
    57 inline ll lca(ll x,ll y){//当两个点位于同一条重链上即结束操作。否则深度深的点跳到所在重链的上一个点,结束操作时深度浅的点的位置即为所求lca
    58     while(top[x]!=top[y]){
    59         if(d[top[x]]<d[top[y]]) swap(x,y);
    60         x=fa[top[x]];
    61     }
    62     if(d[x]>d[y]) swap(x,y);
    63     return x;
    64 }
    65
    66 int main(){
    67     n=read(),m=read(),s=read();
    68     For(i,1,n-1) {x=read(),y=read(),add(x,y),add(y,x);}
    69     dfs1(s),dfs2(s);
    70     For(i,1,m){x=read(),y=read(),printf("%lld\n",lca(x,y));}
    71     return 0;
    72 }

原文地址:https://www.cnblogs.com/wi1d3on/p/11330922.html

时间: 2024-08-02 11:42:32

树剖求LCA模板的相关文章

【树剖求LCA】树剖知识点

#include<cstdio> #include<iostream> using namespace std; struct edge{ int to,ne; }e[1000005]; int n,m,s,ecnt,head[500005],dep[500005],siz[500005],son[500005],top[500005],f[500005]; void add(int x,int y) //加边 { e[++ecnt].to=y; e[ecnt].ne=head[x

最近公共祖先(LCA)问题的树剖实现 (模板)

我来存个档,防止忘记!2333 传送门:https://daniu.luogu.org/problem/show?pid=3379 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输

倍增求lca模板

https://www.luogu.org/problem/show?pid=3379 #include<cstdio> #include<iostream> #include<cmath> #include<cstring> using namespace std; int t,n,cnt,m; int x,y; int f[500001][20],p,root; int fa[500001]; int id[500001]; int head[50000

Tarjan求LCA模板

1 int n,m,hcnt,qcnt; 2 int sx,sy; 3 struct Node{ 4 int to,next; 5 }node[maxn]; 6 struct Query{ 7 int x,ne; 8 int i; 9 }query[maxn<<1]; 10 int head[maxn],vis[maxn],indu[maxn]; 11 int fp[maxn],anc[maxn],que[maxn],ans[maxn<<1]; 12 int findp(int x

LCA模板(数剖实现)

题目链接:https://www.luogu.org/problemnew/show/P3379 题意:LCA模板题. 思路:今天开始学树剖,先拿lca练练.树剖解lca,两次dfs复杂度均为O(n),每次查询为logn,因此总复杂度为:O(2*n+m*logn). 代码: #include<cstdio> #include<cstring> using namespace std; const int maxn=500005; struct node{ int v,next; }

tarjan,树剖,倍增求lca

1.tarjan求lca Tarjan(u)//marge和find为并查集合并函数和查找函数 { for each(u,v) //访问所有u子节点v { Tarjan(v); //继续往下遍历 marge(u,v); //合并v到u上 标记v被访问过; } for each(u,e) //访问所有和u有询问关系的e { 如果e被访问过; u,e的最近公共祖先为find(e); } } 2.倍增lca(在线) #include<bits/stdc++.h> using namespace st

POJ-1330&amp;HDU-2586 最近公共祖先(不带权+带权)树剖式写法求LCA

其实敲树剖敲多了就会手敲,然后就发现其实树剖也是可以求LCA的,根据树剖的经验,我们两遍dfs后关于询问l,r的情况我们就开始跳链,当l,r处于同一个链的时候返回深度较小的那个点就好了,这里给个例题: 题目链接:http://poj.org/problem?id=1330 Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown

HDU 5296 Annoying problem(LCA模板+树的dfs序心得)

Problem Description Coco has a tree, whose nodes are conveniently labeled by 1,2,-,n, which has n-1 edge,each edge has a weight. An existing set S is initially empty. Now there are two kinds of operation: 1 x: If the node x is not in the set S, add n

【BZOJ3626】【LNOI2014】LCA (树剖+离线)

Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)].(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)答案对201314取模. 这个题是大饺子安利给我的,然后顺带学了一发树剖(好弱啊). 这个题解讲的很好啦w:http://www.cnbl