SPOJ 913 Query on a tree II (tree link splitting + multiplication), spoj913
Question link ~~>
Question recognition:I feel more enriched.
Solution: Tree link splitting + Multiplication
At the beginning, the first question is okay, and the second question does not know how to solve it. In fact, both questions can be solved by multiplication.
Let me explain the multiplication I understand: When we record the 2nd ^ I ancestor of the u node, and then find the k ancestor of the u, it is equivalent to using 2 ^ I to combine k, continuously Rising, always reaching the k node. In fact, each update is at the position of 1 in the k binary. For example, to compute the 5th ancestor nodes of u (not including u here), first reach the U' node, then from U', to u'' (Binary 101 of 5 ). After doubling the algorithm, we can do it well. When we calculate the first question, dis = dis [u] + dis [v]-2 * dis [LCA (u, v)], the second question is to judge whether the required point is on the link from u to the intersection point or on the link from v to the intersection point, and then combine the doubling to make it OK.
Code:
# Include <iostream> # include <sstream> # include <map> # include <cmath> # include <fstream> # include <queue> # include <vector> # include <sstream> # include <cstring> # include <cstdio> # include <stack> # include <bitset> # include <ctime> # include <string> # include <cctype> # include <iomanip> # include <algorithm> using namespace std; # define INT long int # define L (x) (x * 2) # define R (x) (x * 2 + 1) const int INF = 0x3f3f3f; const do Uble esp = 0.0000000001; const double PI = acos (-1.0); const INT mod = 1000000007; const int MY = 1400 + 5; const int MX = 20000 + 5; int num, S = 20, n; int head [MX], dep [MX], dis [MX], p [MX] [30]; struct NODE {int v, w, next;} E [MX]; void addedge (int u, int v, int w) {E [num]. v = v; E [num]. w = w; E [num]. next = head [u]; head [u] = num ++; E [num]. v = u; E [num]. w = w; E [num]. next = head [v]; head [V] = num ++;} void dfs_find (int u, int fa, int w) // processing depth, distance {dep [u] = dep [fa] + 1; dis [u] = w; p [u] [0] = fa; for (int I = 1; I <= S; ++ I) // process the ancestor p [u] [I] = p [p [u] [I-1] [I-1]; for (int I = head [u]; I! =-1; I = E [I]. next) {int v = E [I]. v; if (v = fa) continue; dfs_find (v, u, w + E [I]. w) ;}} int LCA (int u, int v) // calculate the public intersection {if (dep [u]> dep [v]) swap (u, v ); // The depth of u is smaller than or equal to v if (dep [u] <dep [v]) // process it into the same depth {int d = dep [v]-dep [u]; // depth difference for (int I = 0; I <S; ++ I) if (d & (1 <I )) v = p [v] [I];} if (u! = V) // It has become the same depth {for (int I = S; I> = 0; -- I) if (p [u] [I]! = P [v] [I]) {u = p [u] [I]; v = p [v] [I];} u = p [u] [0]; v = p [v] [0];} return u;} int cunt (int u, int k) // calculate the k node of u {for (int I = 0; I <S; ++ I) if (k & (1 <I )) u = p [u] [I]; return u;} int Query (int u, int v, int k) // The k node from u to v {int z = LCA (u, v ); // public intersection if (dep [u]-dep [z] + 1> = k) // return cunt (u, k-1) on the chain of u ); else // on the v line {k-= dep [u]-dep [z]; k = dep [v]-dep [z]-k + 1; return cunt (v, k) ;}} int main () {// freopen ("input.txt", "r", stdin); char s [10]; int Tx, u, v, w, k; scanf ("% d", & Tx); while (Tx --) {scanf ("% d", & n); num = 0; memset (head,-1, sizeof (head); for (int I = 1; I <n; ++ I) {scanf ("% d ", & u, & v, & w); addedge (u, v, w);} dep [1] = 0; dfs_find (1, 1, 0 ); while (scanf ("% s", s) & strcmp (s, "DONE") {if (s [0] = 'D ') // calculate the distance between any two points {scanf ("% d", & u, & v); printf ("% d \ n ", dis [u] + dis [v]-2 * dis [LCA (u, v)]);} else // ask the k node {scanf ("% d", & u, & v, & k); printf ("% d \ n ", query (u, v, k) ;}} return 0 ;}