码迷,mamicode.com
首页 > 其他好文 > 详细

[模板]最近公共祖先(LCA)

时间:2018-02-18 10:30:06      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:log   next   --   ++i   https   include   lap   树链剖分   root   

https://www.luogu.org/problemnew/show/P3379

技术分享图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 inline int read(){
 5     register int c = getchar(), x = 0;
 6     while(!isdigit(c)) c = getchar();
 7     while(isdigit(c)) x = (x<<3)+(x<<1)+(c^48), c = getchar();
 8     return x;
 9 }
10 const int MAXN = 500010;
11 int siz[MAXN], anc[MAXN], son[MAXN], top[MAXN], dep[MAXN], l[MAXN], tot, head[MAXN], idx;
12 struct Edge{int v, next;}G[MAXN<<1];
13 inline void addedge(int u, int v){
14     G[++tot].v=v, G[tot].next=head[u], head[u]=tot;
15     G[++tot].v=u, G[tot].next=head[v], head[v]=tot;
16 }
17 //top是重链的起始点 
18 //dfs1维护子树大小和重链
19 //dfs2连接重边形成重链,以根节点为起点,沿着重边向下拓展,拉成重链,不在当前重链上的
20 //节点,以该节点为起点向下重新拉一条重链。
21 //剖分完后每条重链就是一段区间,可以用数据结构维护,
22 //把所有重链首尾相接放到数据结构上维护整体 (暂时没懂) 
23 #define cur G[i].v
24 inline void dfs1(int u){
25     siz[u] = 1; dep[u] = dep[anc[u]] + 1;
26     for(int i = head[u]; i; i = G[i].next){
27         if (cur == anc[u]) continue;
28         anc[cur] = u;
29         dfs1(cur), siz[u] += siz[cur];
30         if (siz[cur] > siz[son[u]]) son[u] = cur;
31     }
32 }
33 
34 inline void dfs2(int u, int t){
35     top[u] = t; 
36     if (son[u]) dfs2(son[u], t);
37     for(int i = head[u]; i; i = G[i].next)
38         if (cur != son[u] && cur != anc[u]) dfs2(cur, cur);
39 }
40 #undef cur
41 inline int query(int u, int v){
42     while(top[u] != top[v]){
43         dep[top[u]] >= dep[top[v]] ? u = anc[top[u]] : v = anc[top[v]];
44     }
45     return dep[u] < dep[v] ? u : v;
46 }
47 int main(void){
48     //freopen("data.in", "r", stdin);
49     int n = read(), m = read(), s = read();
50     for(int u, v, i = 1; i < n; ++i)
51         u = read(), v = read(), addedge(u, v);
52     dfs1(s);
53     dfs2(s,s);
54     while(m--){
55         int u = read(), v = read();
56         printf("%d\n", query(u, v));
57     }
58     return 0;
59 }
树链剖分
技术分享图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 #define N 500010
 7 #define lop(i,a,b) for(register int i = a;i < b; ++i)
 8 int tot, head[N], deep[N], anc[N][20];    int Q, n, m, root;
 9 struct Edge{int v, next;}g[N<<1];
10 inline int read(){
11     register int c = getchar(),f = 1, x = 0;
12     while (!isdigit(c)){if (c == -) f = -1;c = getchar();}
13     while (isdigit(c)){x = x * 10 + c - 0; c = getchar();}
14     return x * f;
15 }
16 inline void init(){
17     for(int j = 1; j <= 18; ++j)
18         for(int i = 1; i <= n; ++i)
19             anc[i][j] = anc[anc[i][j-1]][j-1];
20 }
21 inline void addedge(int u, int v){
22     g[++tot].v = v;g[tot].next=head[u];head[u]=tot;
23     g[++tot].v = u;g[tot].next=head[v];head[v]=tot;
24 }
25 inline void dfs(int u, int fa, int depth){
26     anc[u][0] = fa;
27     deep[u] = depth;
28     for(register int i = head[u];i;i=g[i].next){
29         int v = g[i].v;if (v == fa)continue;
30         dfs(v, u , depth+1);
31     }
32 }
33 inline int LCA(int u, int v){
34     if (deep[u] < deep[v]) swap(u, v);
35     for(int i = 18; i >= 0; --i){if (deep[anc[u][i]] >= deep[v])u=anc[u][i];}
36     if (u == v) return u;
37     for(int i = 18; i >= 0; --i)
38     if (anc[u][i] != anc[v][i])
39     u=anc[u][i],v=anc[v][i];
40     return anc[u][0];
41 }
42 int main(void){
43     n = read(),Q=read(),root=read();
44     lop(i,1,n){
45         addedge(read(), read());
46     }
47     dfs(root, root, 0);init();
48     while (Q--){
49         printf("%d\n", LCA(read(), read()));
50     }
51     return 0;
52 }
倍增

 

[模板]最近公共祖先(LCA)

标签:log   next   --   ++i   https   include   lap   树链剖分   root   

原文地址:https://www.cnblogs.com/Ycrpro/p/8452482.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!