Location>code7788 >text

Recent public ancestor templates

Popularity:330 ℃/2025-04-05 18:52:10

Recent public ancestors

topic:/?pid=2586

#include <bits/stdc++.h>
 using u32 = unsigned;
 using i64 = long long;
 using u64 = unsigned long long;
 //
 const int N = 50010;
 int f[N][20], d[N], dist[N];
 int e[2*N], ne[2*N], w[2*N], h[2*N], idx;
 int n, m, t;
 void add(int a, int b, int c) {
	 e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
 }
 std::queue<int> q;
 void bfs() {
	 (1); // Add root node
	 d[1] = 1; // The level of the root node is 1
	 while (()) {
		 int x = ();
		 ();
		 for (int i = h[x]; i != -1; i = ne[i]) {
			 int y = e[i];
			 if (d[y] != -1) continue; // y has been traversed and the depth has been assigned to it
			 d[y] = d[x] + 1; // The level of y is equal to the level of x plus one
			 dist[y] = dist[x] + w[i]; // The distance from y to the root node is the distance from x to the root node plus the size of the edge (x,y)
			 f[y][0] = x; // y moves upwards to 2 to reach x
			 for (int j = 1; j <= t; j ++) {
				 f[y][j] = f[f[y][j-1]][j-1]; // The point you reach when you walk y upwards 2^j step is: the point you reach when you walk y upwards 2^(j-1) step, and then upwards 2^(j-1) step
			 }
			 (y); // Join the queue
		 }
	 }
 }

 int lca(int x, int y) {
	 if (d[x] < d[y]) std::swap(x, y); // Make the level of x greater than the level of y
	 for (int i = t; i >= 0; i --) {
		 if (d[f[x][i]] >= d[y]) {
			 // The steps to the power of x are still greater than the depth of y, so you have to continue walking
			 x = f[x][i];
		 }
	 }
	 if (x == y) return y; // After the walk, x and y are equal, then y is the most recent public ancestor. Because y has a relatively large depth, y should be the ancestor
	 // Otherwise, the depths of these two points should be equal
	 for (int i = t; i >= 0; i --) {
		 // Move up at the same time
		 if (f[x][i] != f[y][i]) {
			 x = f[x][i];
			 y = f[y][i];
		 }
	 }
	 return f[x][0]; // In the end, the parent node of these two points is the nearest public ancestor
 }

 int main()
 {
	 int T;
	 std::cin >> T;
	 while (T --) {
		 std::cin >> n >> m;
		 t = (int)(log(n) / log(2)) + 1;
		 // Clear
		 memset(h, -1, sizeof h);
		 memset(d, -1, sizeof d);
		 idx = 0;
		 // Read into a tree
		 for (int i = 1; i < n; i ++) {
			 int x, y, z;
			 std::cin >> x >> y >> z;
			 add(x, y, z);
			 add(y, x, z);
		 }
		 bfs(); // Preprocessing information
		 // answer the questions
		 for (int i = 1; i <= m; i ++) {
			 int x, y;
			 std::cin >> x >> y;
			 std::cout << dist[x] + dist[y] - 2 * dist[lca(x, y)] << "\n"; // The distance between two points is the sum of the distance between the two points and the root node minus 2 times the distance between the closest public ancestor and the root node
		 }
	 }
	 return 0;
 }

Several important points
1. t: The longest path from the leaf node to the root node (to the power of 2)
t = (int)(std::log(n) / std::log(2)) + 1;
2. f[i][j]: The point that can be reached by walking upward from point i to the power of 2^j, such as f[i][0] = father[i] (go upward from step 2^0 to reach the parent node)
When traversing the child node of the current node x and using y, the method of f[y][j] is as follows:

f[y][0] = x;
 for (int j = 1; j <= t; j ++) {
     f[y][j] = f[f[y][j-1]][j-1]; // The point you reach when you walk y upwards 2^j step is: the point you reach when you walk y upwards 2^(j-1) step, and then upwards 2^(j-1) step
 }

3. d[x]: The depth of point x, its parent node is represented by px
Initialize the d array to -1 to determine whether the current point has been traversed. If the current point is not traversed, then d[x] = d[px] + 1;
4. dist[x]: The distance from point x to the root node, its parent node is represented by px, and the weight of edge (px, x) is represented by w[i]
Initialize the d array to 0. If the current point has not been traversed, then dist[x] = dist[px] + w[i];
5. Find the nearest common ancestor of x and y:
If the depth of x is less than the depth of y, exchange x and y, and unified as the depth of x is greater than or equal to the depth of y

for (int i = t; i >= 0; i --) {
	 if (d[f[x][i]] >= d[y]) {
		 // The steps to the power of x are still greater than the depth of y, so you have to continue walking
		 x = f[x][i];
	 }
 }

After executing the above code, the depth of x and y may be the same, or x is equal to y (y is the ancestor of x)
-------1) If x and y are equal, then return y directly, and y is the most recent public ancestor
-------2) Otherwise, the depth of x and y is the same, and go up together

for (int i = t; i >= 0; i --) {
	 // Move up at the same time
	 if (f[x][i] != f[y][i]) {
	     x = f[x][i];
		 y = f[y][i];
	 }
 }

After this end, they should meet the upward 2^i power steps and they are equal.
The last parent node of x is f[x][0], which is the answer