别的不说,先%为敬%%%%%%%%%
写个LCA,跑的比HKjournalistTarjan还快,把倍增吊起来打......
反正就是那样,重儿子是为了保证时间复杂度。
DFS_1要求出d,fa,son,siz
DFS_2要求出top,id(剖出来的下标)
基本思路是靠着top最多会经过log次,不断跳top
重链剖出来是连续的,可以区间操作。
树剖求LCA:
1 #include <cstdio> 2 3 const int N = 500010; 4 5 struct Edge { 6 int v, nex; 7 }edge[N << 1]; int t; 8 int e[N], A[N], root, num; 9 int top[N], son[N], fa[N], siz[N], id[N], d[N]; 10 11 inline void add(int x, int y) { 12 t++; 13 edge[t].v = y; 14 edge[t].nex = e[x]; 15 e[x] = t; 16 return; 17 } 18 19 void DFS_1(int x, int deep, int f) { 20 d[x] = deep; 21 siz[x] = 1; 22 fa[x] = f; 23 for(int i = e[x]; i; i = edge[i].nex) { 24 int y = edge[i].v; 25 if(y == f) { 26 continue; 27 } 28 DFS_1(y, deep + 1, x); 29 siz[x] += siz[y]; 30 if(siz[y] > siz[son[x]]) { 31 son[x] = y; 32 } 33 } 34 return; 35 } 36 37 void DFS_2(int x, int k) { 38 top[x] = k; 39 id[x] = ++num; 40 A[num] = x; 41 if(son[x]) { 42 DFS_2(son[x], k); 43 } 44 for(int i = e[x]; i; i = edge[i].nex) { 45 int y = edge[i].v; 46 if(y == son[x] || y == fa[x]) { 47 continue; 48 } 49 DFS_2(y, y); 50 } 51 return; 52 } 53 54 inline int lca(int x, int y) { 55 while(top[x] != top[y]) { 56 if(d[top[x]] > d[top[y]]) { 57 x = fa[top[x]]; 58 } 59 else { 60 y = fa[top[y]]; 61 } 62 } 63 return d[x] > d[y] ? y : x; 64 } 65 66 int main() { 67 int n, m; 68 scanf("%d%d%d", &n, &m, &root); 69 int x, y; 70 for(int i = 1; i < n; i++) { 71 scanf("%d%d", &x, &y); 72 add(x, y); 73 add(y, x); 74 } 75 DFS_1(root, 1, 0); 76 DFS_2(root, root); 77 while(m--) { 78 scanf("%d%d", &x, &y); 79 printf("%d\n", lca(x, y)); 80 } 81 return 0; 82 }