思路:
建立一个树,以1为根,计算出每个点和根节点所在树的直径d1,并算出每个点距离根节点的距离d2。然后,模拟两个出发点根节点1和x点,让x点向根节点靠近,根节点向x点靠近。当根节点的步数小于x点(x点在更新,用并查集维护)到根节点距离时记录d2 * 2(可以到达的点),其余情况为不能到达。
#include <bits/stdc++.h>
#define max_n 200010
using namespace std;
typedef long long LL;
int pre[max_n], d1[max_n], d2[max_n];
vector<int> v[max_n];
int n, x, p1, p2;
void dfs(int now, int next, int step) {
d1[now] = d2[now] = step;
pre[now] = next;
for(int i = 0; i < v[now].size(); i++) {
int temp = v[now][i];
if(temp != next) { //为了不重复,只需要不和父节点相同即可
dfs(temp, now, step + 1);
d2[now] = max(d2[now], d2[temp]);
}
}
}
int main() {
scanf("%d %d", &n, &x);
for(int i = 0; i < n - 1; i++) {
scanf("%d %d", &p1, &p2);
v[p1].push_back(p2);
v[p2].push_back(p1);
}
dfs(1, 1, 0);
int ans = 2 * d2[x];
int k = x;
// for(int i = 1; i <= n; i++) {
// printf("%d -> %d -> %d -> %d\n", i, d1[i], d2[i], pre[i]);
// }
for(int i = 0; i < d1[x]; i++) {
// printf("%d -> %d -> %d\n", k, d1[k], d2[k]);
if(i < d1[k]) {
ans = max(2 * d2[k], ans);
}
else break;
k = pre[k];
}
printf("%d\n", ans);
return 0;
}
/*
7 7
1 2
2 3
7 3
4 3
4 6
4 5
*/