1. 程式人生 > >[模板]最近公共祖先(LCA)

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

一段 post 大小 const fin cstring https string print

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)