///O(n). #include #define aaa system("read -r -p \"Press enter to continue...\" key"); #define dbg(x) std::cerr<<(#x)<<": "<<(x)<<'\n',aaa #define dbga(x,n) std::cerr<<(#x)<<"[]: ";for(int _=0;_ g[maxn]; int df_index = 0, df_time = 0; int df_poz[maxn], tata[maxn], subtree_size[maxn], depth[maxn]; std::pair df_times[maxn]; bool switches[maxn]; ///nodurile din care avem voie sa schimbam din bfs in dfs (sau invers), e.g. toti ancestorii lui k. void dfs(int nod, int t) { tata[nod] = t; if (t != -1) depth[nod] = 1 + depth[t]; df_poz[nod] = df_index++; df_times[nod].first = df_time++; for (int nn: g[nod]) if (nn != t) dfs(nn, nod); df_times[nod].second = df_time++; } ///am nevoie de subtree_size doar ca sa determin indexul lui k in bfs(z). astfel calculez subtree_size doar pana la depth[k]. void dfs_subtree_k(int k, int nod, int t) { subtree_size[nod] = 1; for (int nn: g[nod]) { if (nn != t && depth[nod] < depth[k]) { dfs_subtree_k(k, nn, nod); subtree_size[nod] += subtree_size[nn]; } } } ///intoarce toate nodurile din coada bfs-ului care sunt la aceeasi adancime ca k. std::vector bfs_get_same_width_k(int n, int k) { std::array, 2> queues = {std::vector{0}, {}}; int pin = 0; // while (!queues[pin].empty() && std::find(queues[pin].begin(), queues[pin].end(), k) == queues[pin].end()) { for (int _ = 0; _ < depth[k]; _++) { for (int nod: queues[pin]) { for (int nn: g[nod]) { if (nn != tata[nod]) queues[pin^1].push_back(nn); } } queues[pin].clear(); pin ^= 1; } return queues[pin]; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); int n, k; std::cin >> n >> k; k--; for (int i = 0; i < n-1; i++) { int a, b; std::cin >> a >> b; a--; b--; g[a].push_back(b); g[b].push_back(a); } dfs(0, -1); dfs_subtree_k(k, 0, -1); std::vector nodes_depth_as_k = bfs_get_same_width_k(n, k); int ind_k = std::find(nodes_depth_as_k.begin(), nodes_depth_as_k.end(), k) - nodes_depth_as_k.begin(), ind_last_in_subtree = ind_k; int z = k, ans_dfs_bfs = inf; while (z != -1) { ///calculez pe ce pozitie ar fi k daca incep bfs din z. ///pozitia e: subtree_size[z] - cate noduri de la aceeasi adancime ca k sunt la dreapta lui k. ///obs: cu cat merg mai sus in arbore, voi continua sa cuprind nodurile deja numarate + optional altele. while ( ind_last_in_subtree + 1 < (int)nodes_depth_as_k.size() && df_times[z].first < df_times[nodes_depth_as_k[ind_last_in_subtree+1]].first && df_times[nodes_depth_as_k[ind_last_in_subtree+1]].second < df_times[z].second ) { ind_last_in_subtree++; } int curr_ans = df_poz[z] + subtree_size[z] - (ind_last_in_subtree - ind_k); if (ans_dfs_bfs > curr_ans) { ans_dfs_bfs = curr_ans; } switches[z] = true; z = tata[z]; } int ans_bfs_dfs = inf, bfs_iter = 0; std::queue qu; qu.push(0); while (!qu.empty()) { int nod = qu.front(); qu.pop(); bfs_iter++; if (switches[nod]) { ans_bfs_dfs = std::min(ans_bfs_dfs, bfs_iter + df_poz[k] - df_poz[nod]); } for (int nn: g[nod]) { if (nn != tata[nod]) qu.push(nn); } } std::cout << ans_bfs_dfs << '\n' << ans_dfs_bfs << '\n'; return 0; }