Running in the tree [Eulerian sequence] [Conclusion]

Keywords: Algorithm Graph Theory


ybtoj running in trees


Xiao A will run on A rooted tree with 1 as the root and N nodes every day. At the beginning, each node has an obstacle. Each obstacle will move periodically in the subtree with the initial point as the root according to the order of depth first, and only one edge will be moved per unit time.

Small A starts at point x. he wants to run to the root node along the shortest path, and he will only move one edge per unit time. In this process, if Xiao A encounters an obstacle at A node, he needs to consume some energy to clear it, and the cleared obstacle will not appear again.

Please find out how much energy small A needs to consume to reach the end.

n ā‰¤ 5 āˆ— 1 0 5 n\le 5*10^5 nā‰¤5āˆ—105

>Problem solving ideas

After studying the nature of the problem, it is found that only the point on the path x to 1 can meet Xiao A, and if it is not encountered in the first motion cycle, it will not be encountered in the future (if it is not encountered in one motion, it means Xiao A has found it)
So we only need to consider the initial point on the x to 1 path, and we don't need to consider the periodic motion, so we can study the first motion

We list the trajectories of the first motion cycle of node 1. Obviously, the trajectories of all nodes are included
Moreover, we find that it searches all points deeply. When a subtree is added and searched, the number of times a point appears in the sequence is its degree
In fact, this is the Euler order (another kind of Euler order is that when all subtrees are added and searched, the number of occurrences is 2)

After finding out the Euler order of the tree, we can start to find the obstacles to be removed
Jump up from X and encounter a point. Suppose we meet some obstacles at this point. We already know the time, and we can find the original position of these obstacles in the Euler sequence. If they start on the path x to 1, these obstacles will be encountered
Note that if we want to remove obstacles, we should mark them in their original position to prevent an obstacle from being removed again
And when we encounter a point, we need to find all its positions in the Euler sequence, because there may be multiple obstacles in one position, which should be removed


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define N 500010
using namespace std;

vector<int> pos[N];
struct edge
	int to, nxt;
} e[N];
int T, n, m, cnt, h[N], pp[N], q[N * 2], tot, dep[N], fa[N], x, ans;
bool ok[N], fst[N * 2];

void dfs (int now, int fath)
	q[++tot] = now, fst[tot] = 1;
	pos[now].push_back (tot);
	fa[now] = fath;
	dep[now] = dep[fath] + 1;
	for (int i = h[now]; i; i = e[i].nxt)
		dfs (e[i].to, now);
		q[++tot] = now;
		pos[now].push_back (tot);
void work ()
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf ("%d", &m);
		for (int j = 1; j <= m; j++) scanf ("%d", &pp[j]);
		for (int j = m; j >= 1; j--)
		  e[++cnt] = (edge){pp[j], h[i]}, h[i] = cnt;
	dfs (1, 0);
	scanf ("%d", &x);
//	for (int i = 1; i <= tot; i++) printf ("%d ", q[i]);
//	printf ("\n");
	int now = x, tim, y, len;
	for (; now; now = fa[now]) ok[now] = 1;
	now = x;
	for (; now; now = fa[now])
		tim = dep[x] - dep[now];
		len = pos[now].size();
		for (int i = 0; i < len; i++)
			y = pos[now][i] - tim;
			if (y <= 0 || !ok[q[y]] || !fst[y]) continue;
			ok[q[y]] = 0, ans++;
	printf ("%d\n", ans);
	for (int i = 1; i <= n; i++)
	  h[i] = fa[i] = dep[i] = ok[i] = 0;
	for (int i = 1; i <= tot; i++) q[i] = fst[i] = 0;
	for (int i = 1; i <= n; i++)
	  while (!pos[i].empty()) pos[i].pop_back();
	cnt = tot = ans = 0;

int main()
	freopen ("", "r", stdin);
	freopen ("run.out", "w", stdout);
	scanf ("%d", &T);
	while (T--)
	  work ();
	return 0;

Posted by demonicfoetus on Mon, 08 Nov 2021 17:47:46 -0800