题意:给定一棵树,从树中的任意选一个顶点出发,遍历K个点的最短距离是多少?(每条边的长度为1)
解析:就是求树的直径,假设求出的树的最长链所包含的点数为m,那么如果K<=m,那么答案就是K-1,否则就是(K-m)*2+m-1
好多人是用bfs求的,而我采用的是dfs,假设当前节点为父节点,记录它到达子节点的两个最大的深度,
树的直径就是这两个深度所有和里面的最大值,每次返回最大深度+1。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 200100
struct Graph{
int e, first[N], next[N], v[N];
void init(){memset(first, -1, sizeof(first)); e = 0;}
void input(int a,int b){
v[e] = b; next[e] = first[a]; first[a] = e++;
v[e] = a; next[e] = first[b]; first[b] = e++;
}
}T;
int mh;
int dfs(int u,int f){
int m1, m2;
m1 = m2 =0;
int Maxh = 0;
for(int i = T.first[u]; i != -1; i = T.next[i]){
int v = T.v[i];
if(v == f) continue;
int h = dfs(v,u);
if(h > Maxh) Maxh = h;
if(h > m1){
m2 = m1;
m1 = h;
}
else if(h > m2){
m2 = h;
}
}
mh = max(mh, m1 + m2);
return Maxh + 1;
}
int main()
{
// freopen("in","r",stdin);
int caseNum;
scanf("%d",&caseNum);
while(caseNum--){
int n, m;
scanf("%d%d",&n,&m);
T.init();
for(int i = 0; i < n-1; i++){
int u, v;
scanf("%d%d",&u,&v);
T.input(u,v);
}
mh = 0;
dfs(1,0);
for(int i = 0; i < m; i++){
int tmp;
scanf("%d",&tmp);
tmp--;
if(tmp <= mh){
printf("%d\n",tmp);
}
else {
printf("%d\n",2 * tmp - mh);
}
}
}
return 0;
}