Park Visit
题意:公园里有n个景点,n-1条距离相等的将这n个点构成一棵树,问任选一点开始参观公园,可以逛完k个景点所要走的最短路径;
思路:如果树的直径为m,即树的叶节点到叶节点之间最长距离为m, 当k<=m+1时,不用走回头路,这样是最短的,此时最短路径为k-1; 当k>m+1时并定会走重复的路,我们的目标就是让重复的路最短;要想让重复的路最短那么一定走完了树的直径,至于从重复的路便是到其他节点的了路;此时最短路为 m+(k-(m+1))*2;
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1e5+10;
int N, M;
vector<int> vec[maxn];
int dis[maxn], vis[maxn];
void dfs(int x){
vis[x]=1;
for(int i=0; i<vec[x].size(); i++){
int v=vec[x][i];
if(vis[v]) continue;
dis[v]=dis[x]+1;
dfs(v);
}
}
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%d%d", &N, &M);
for(int i=0; i<=N; i++) vec[i].clear();
for(int i=1; i<N; i++){
int u, v;
scanf("%d%d", &u, &v);
vec[u].push_back(v);
vec[v].push_back(u);
}
memset(vis, 0, sizeof(vis));
memset(dis, 0, sizeof(dis));
dfs(1);
int s, temp=0;
for(int i=1; i<=N; i++){
if(dis[i]>temp){
temp=dis[i];
s=i;
}
}
memset(vis, 0, sizeof(vis));
memset(dis, 0, sizeof(dis));
dfs(s);
temp=0;
for(int i=1; i<=N; i++){
if(temp<dis[i]) temp=dis[i];
}
while(M--){
int k;
scanf("%d", &k);
if(k<=temp) printf("%d\n", k-1);
else printf("%d\n", temp+(k-(temp+1))*2);
}
}
return 0;
}