[模板] 树链剖分找LCA

#include <cstdio>
#include <cstring>
#define MAX 500005

int d[MAX],fa[MAX],size[MAX],top[MAX],son[MAX];
int N,M,S,tot=0;
int head[MAX];

struct edge{
    int v,next;
}G[MAX<<1];

inline void add(int u,int v){
    G[++tot].v=v;G[tot].next=head[u];head[u]=tot;
}

inline void dfs1(int u,int father){
    d[u]=d[father]+1;
    fa[u]=father;
    size[u]=1;
    int max = 0;
    for(register int i=head[u];i;i=G[i].next){
        int v = G[i].v;
        if(v==father)continue;
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>max)son[u]=v,max=size[v];
    }
}

inline void dfs2(int u,int high,int father){
    top[u]=high;
    if(son[u]==0)return;
    dfs2(son[u],high,u);
    for(register int i=head[u];i;i=G[i].next){
        int v = G[i].v;
        if(v==son[u]||v==father)continue;
        dfs2(v,v,u);
    }
}

inline void swap(int* u,int* v){
    int t = *u;*u = *v;*v = t;
}

inline int LCA(int u,int v){
    while(top[u]!=top[v]){
        if(d[top[u]]<d[top[v]])swap(&u,&v);
        u = fa[top[u]];
    }
    return d[u]>d[v]?v:u;
}
int main(){

    std::memset(head,0,sizeof(head));
    std::memset(son,0,sizeof(son));

    scanf("%d%d%d",&N,&M,&S);
    int u,v;
    for(register int i=1;i<N;++i){
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }

    d[0]=0;

    dfs1(S,0);
    dfs2(S,0,0);

    for(register int i=1;i<=M;++i){
        scanf("%d%d",&u,&v);
        printf("%d\n",LCA(u,v));
    }
    return 0;
}
 

原文地址:https://www.cnblogs.com/Neworld2002/p/8641002.html

时间: 2024-10-05 04:02:24

[模板] 树链剖分找LCA的相关文章

[luogu P3384] [模板]树链剖分

[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数

luoguP3384 [模板]树链剖分

luogu P3384 [模板]树链剖分 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algorithm> #include<ctime> #include<queue> #define rg register

BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=2243 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”. 请你写

hdu 5242 树链剖分找权值最大的前k条链

http://acm.hdu.edu.cn/showproblem.php?pid=5242 Problem Description It is well known that Keima Katsuragi is The Capturing God because of his exceptional skills and experience in ''capturing'' virtual girls in gal games. He is able to play k games sim

P2633|主席树+dfs序+树链剖分求lca+离散化

不知道为什么会RE.. 待补 思路:链上求u和v两点路径第k小利用lca就转变为了 U+V-LCA-FA(LCA) 上的第k小,这因为每个点的主席树的root是从其父转移来的.可以用树链剖分求lca:在dfs序上建立主席树将树上问题转变为区间问题,询问的时候用主席树求区间k小值. 终于能写出这种题了,开心! #include<bits/stdc++.h> using namespace std; const int maxn = 1e5+100; int n,m,e = 1,num,ans=0

树链剖分求LCA

这里先推荐两道练习的裸题 首先是求点 [codevs4605] LCA 就是求两个点的公共祖先,每次询问xor上上一个询问的答案. 先是两遍DFS: dfs1:把dep.siz.son求出来 dfs2:求出top和w siz[v]表示以v为根的子树的节点数 dep[v]表示v的深度(根深度为1) top[v]表示v所在的链的顶端节点 fa[v]表示v的父亲 son[v]表示与v在同一重链上的v的儿子节点 w[v]结点编号 int lca(int x,int y){ while (top[x]!=

[模板]树链剖分

原题链接:https://www.luogu.org/problemnew/show/P3384 树链剖分+线段树,备用. 等待补充详细解释中. /* 1 x y z x到y最短路径上加上z 2 x y 求x到y的最短路径上的节点值之和 3 x z 以x为根节点的子树内的所有节点值都加上z 4 x 以x为根节点的所有节点值之和 */ #include<cstdio> void read(int &y) { y=0;char x=getchar();int f=1; while(x<

【模板】树链剖分求LCA

洛谷3379 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=500010,inf=1e9; 5 int n,m,x,y,root,tot,dep[maxn],son[maxn],size[maxn],fa[maxn],top[maxn],last[maxn]; 6 struct edge{int to,pre;}e[maxn<<1]; 7 inline v

【POJ1330】Nearest Common Ancestors(树链剖分求LCA)

Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree. Node x is an ancestor of