备战NOIP——模板复习9
这里只有模板,并不作讲解,仅为路过的各位做一个参考以及用做自己复习的资料,转载注明出处。
最近公共祖先(LCA)
树链剖分
/*Copyright: Copyright (c) 2018
*Created on 2018-10-31
*Author: 十甫
*Version 1.0
*Title: LCA_树链剖分
*Time: 8.5 mins
*/
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 10005;
int head[maxn];
struct edge {
int to, next;
} data[maxn * 2];
inline void add_edge(int from, int to, int i) {
data[i] = (edge) {to, head[from]};
head[from] = i;
}
int depth[maxn], f[maxn], son[maxn], top[maxn], size[maxn];
void dfs1(int pos, int d) {
size[pos] = 1, depth[pos] = d;
for(int i = head[pos];i;i = data[i].next) {
int u = data[i].to;
if(u == f[pos]) continue;
f[u] = pos;
dfs1(u, d + 1);
size[pos] += size[u];
if(size[u] > size[son[pos]]) son[pos] = u;
}
}
void dfs2(int pos, int t) {
top[pos] = t;
if(son[pos]) dfs2(son[pos], t);
for(int i = head[pos];i;i = data[i].next) {
int u = data[i].to;
if(u == f[pos] || u == son[pos]) continue;
dfs2(u, u);
}
}
int lca(int a, int b) {
while(top[a] != top[b]) {
if(depth[top[a]] < depth[top[b]]) swap(a, b);
a = f[top[a]];
}
return depth[a] > depth[b] ? b : a;
}
int main() {
int n;
scanf("%d", &n);
for(int i = 1;i < n;i++) {
int a, b;
scanf("%d%d", &a, &b);
add_edge(a, b, i), add_edge(b, a, i + n);
}
dfs1(1, 1);
dfs2(1, 1);
int q;
scanf("%d", &q);
while(q--) {
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", lca(a, b));
}
return 0;
}
倍增
/*Copyright: Copyright (c) 2018
*Created on 2018-10-31
*Author: 十甫
*Version 1.0
*Title: LCA_倍增
*Time: 10 mins
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int size = 10005;
const int maxk = 20;
int head[size];
struct edge {
int to, next;
} data[size * 2];
inline void add_edge(int from, int to, int i) {
data[i] = (edge) {to, head[from]};
head[from] = i;
}
int book[maxk][size], depth[size];
void dfs(int pos, int d) {
depth[pos] = d;
for(int i = head[pos];i;i = data[i].next) {
int u = data[i].to;
if(u == book[0][pos]) continue;
book[0][u] = pos;
dfs(u, d + 1);
}
}
void make(int n) {
for(int k = 1;(1 << k) <= n;k++) {
for(int i = 1;i <= n;i++) {
book[k][i] = book[k - 1][book[k - 1][i]];
}
}
}
inline int lca(int a, int b) {
if(depth[a] < depth[b]) swap(a, b);
for(int k = maxk - 1;k >= 0;k--) {
if(depth[book[k][a]] >= depth[b]) {
a = book[k][a];
}
}
if(a == b) return a;
for(int k = maxk - 1;k >= 0;k--) {
if(book[k][a] != book[k][b]) {
a = book[k][a], b = book[k][b];
}
}
return book[0][a];
}
int main() {
int n;
scanf("%d", &n);
for(int i = 1;i < n;i++) {
int a, b;
scanf("%d%d", &a, &b);
add_edge(a, b, i), add_edge(b, a, i + n);
}
dfs(1, 1);
make(n);
int q;
scanf("%d", &q);
while(q--) {
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", lca(a, b));
}
return 0;
}
NOIP 2018 RP++