備戰NOIP——模板複習9
阿新 • • 發佈:2018-12-18
這裡只有模板,並不作講解,僅為路過的各位做一個參考以及用做自己複習的資料,轉載註明出處。
最近公共祖先(LCA)
樹鏈剖分
/*Copyright: Copyright (c) 2018 *Created on 2018-10-28 *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-28 *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; }