树链剖分求LCA

Posted gE_nis

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树链剖分求LCA相关的知识,希望对你有一定的参考价值。

题目描述

如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

输入输出格式

输入格式:

 

第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。

接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。

接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。

 

输出格式:

 

输出包含M行,每行包含一个正整数,依次为每一个询问的结果。

 

输入输出样例

输入样例#1: 复制
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
输出样例#1: 复制
4
4
1
4
4

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=10,M<=10

对于70%的数据:N<=10000,M<=10000

对于100%的数据:N<=500000,M<=500000

 

 1 //2018年2月17日20:50:56 
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int N = 1000001;
 9 const int M = 1000001;
10 
11 struct Edge{
12     int to, len, nxt;
13 }E[M];
14 int cnt, fir[N], fa[N], top[N], deep[N], siz[N], son[N], val[N];
15 
16 void addEdge(int x, int y, int z=0){
17     E[++cnt].to = y;
18     E[cnt].len = z;
19     E[cnt].nxt = fir[x];
20     fir[x] = cnt;
21 }
22 
23 void dfs1(int x){
24     deep[x] = deep[fa[x]] + 1; siz[x] = 1;
25     for(int i=fir[x]; i; i=E[i].nxt){
26         int to = E[i].to;
27         if(fa[x] != to){
28             val[to] = E[i].len;
29             fa[to] = x;
30             dfs1(to);
31             siz[x] += siz[to];
32             if(siz[son[x]] < siz[to]) son[x] = to;
33         }
34     }
35 }
36 
37 void dfs2(int x){
38     if(x == son[fa[x]]) top[x] = top[fa[x]];
39     else top[x] = x;
40     for(int i=fir[x]; i; i=E[i].nxt)
41         if(fa[E[i].to] == x)  
42             dfs2(E[i].to);
43 }
44 
45 int query(int x, int y){
46     for(; top[x]!=top[y]; deep[top[x]]>deep[top[y]]?x=fa[top[x]]:y=fa[top[y]]); //注意这里有个分号!!! 
47     return deep[x]<deep[y]?x:y;
48 }
49 
50 int n, m, x, y, v, root;
51 int main(){
52     scanf("%d%d%d", &n, &m, &root);
53     for(int i=1;i<n;i++){
54         scanf("%d%d", &x, &y);
55         addEdge(x, y);
56         addEdge(y, x);
57     }
58     dfs1(root);
59     dfs2(root);
60     
61     for(int i=1;i<=m;i++){
62         scanf("%d%d", &x, &y);
63         printf("%d\n", query(x, y));
64     }
65 
66     return 0;
67 }

 

以上是关于树链剖分求LCA的主要内容,如果未能解决你的问题,请参考以下文章

树链剖分洛谷P3379 树链剖分求LCA

模板树链剖分求LCA

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

树链剖分求LCA

Luogu P3379 模板最近公共祖先(LCA),树链剖分求LCA模板

重链剖分求LCA