Sorry.
There are too many methods to solve the problem.
Multiply, Tarjan, St, LCT, HLD ....
I will not write the three behind, but I have never written the st. I don't think it can be used. I just need to multiply online and use Tarjan offline.
Well.
First, multiply (nlogn, online ):
The multiplication idea is used on the tree to find the LCA.
We maintain a two-dimensional array. f [I] [J] indicates the ancestor of point I, 2nd ^ J, obviously 2 ^ 0 = 1, that is, F [I] [0] is his father.
We need to use DFS to maintain a depth array (for LCA)
We also need to multiply to find all f [I] [J]. All those who have learned st should know, here f [I] [J] = f [f [I] [J-1] [J]
Then we need to calculate the LCA. It is very simple. First, we need to adjust the two vertices u and v to the same depth, so that subsequent operations will be in the same depth.
How to adjust the depth? It's easy to subtract their depth. We set it to Dep, so this Dep corresponds to the height that needs to be increased for the deeper point. Well, we should be able to think of it immediately, directly use binary to represent the depth and then climb up all the time. This is the multiplication idea, Log Level
At the same depth, we need to increase at the same time ~ We continue to use the multiplication thought to increase the height of 2 ^ K in turn. When will it rise? Of course, F [u] [k]! = F [v] [K], because it indicates that their ancestors are still different, they are located in two Subtrees, so they need to rise. And the order should be from big to small! Otherwise, it is easy to understand that the smallest ancestor cannot be obtained.
the code is very simple, with 12 lines
# Include <iostream> # include <cstdio> using namespace STD; # define dbg (X) cout <# x <"=" <x <Endl # define read (x) x = getint () # define RDM (u) for (INT I = ihead [u]; I; I = E [I]. next) const int n = 10000, M = 15; inline const int getint () {char c = getchar (); int K = 1, ret = 0; (; c <'0' | C> '9'; C = getchar () if (C = '-') k =-1; (; c> = '0' & C <= '9'; C = getchar () ret = RET * 10 + C-'0'; return K * ret ;} struct ed {int, Next;} e [n <1]; int CNT, ihead [N], n, m, DEP [N], Fa [N] [m]; bool vis [N]; inline void add (const Int & U, const Int & V) {e [++ CNT]. next = ihead [u]; ihead [u] = CNT; E [CNT]. to = V; E [++ CNT]. next = ihead [v]; ihead [v] = CNT; E [CNT]. to = u;} void DFS (const Int & U, const Int & D) {vis [u] = 1; Dep [u] = D; RDM (u) if (! Vis [E [I]. to]) {DFS (E [I]. to, D + 1); Fa [E [I]. to] [0] = u ;}} inline void BZ () {for (Int J = 1; j <m; ++ J) for (INT I = 1; I <= N; + I) Fa [I] [J] = Fa [Fa [I] [J-1] [J-1];} inline int LCA (INT U, int v) {If (DEP [u] <Dep [v]) Swap (u, v); int d = Dep [u]-dep [v]; for (INT I = M-1; I> = 0; -- I) if (1 <I) & D) u = Fa [u] [I]; if (u = V) return U; For (INT I = M-1; I> = 0; -- I) if (Fa [u] [I]! = Fa [v] [I]) u = Fa [u] [I], V = Fa [v] [I]; return Fa [u] [0];} int main () {read (n); read (m); For (INT I = 1; I <n; ++ I) add (getint (), getint (); DFS (1, 1); BZ (); While (M --) printf ("% d \ n", LCA (getint (), getint (); Return 0 ;}