肯定会想到树的直径:
如果直径够长,就在直径(1+8)上面找路径,ans=k。
如果不够长,肯定会在有点分叉点(如3,4,5)回溯,然后我们把路径拉直,把其中一条的作为主线(有机化学,ORZ),主线是线走一遍,而分支走两遍,所以要想答案越小,主线就要求越长,也就是树的直径d,ans=d+(k-d)*2。
如果不好想,可以模拟一下,1--2--3--上--下--4--下--下--上--上--5--上--下--下--上-- 6--7--8....
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
using namespace std;
int dis[100010],ans[100010],Max;
int n,s,t;
vector<int>G[100010];
void _dfs(int v)
{
for(int i=0;i<G[v].size();i++){
if(!dis[G[v][i]]) {
dis[G[v][i]]=dis[v]+1;
_dfs(G[v][i]);
}//任意两个点只有一条路,所以dfs和bfs效果一样
}
}
void _finds()
{
memset(dis,0,sizeof(dis));
dis[1]=1;_dfs(1);s=1;
for(int i=2;i<=n;i++)
if(dis[i]>dis[s]) s=i;
}
void _findt()
{
memset(dis,0,sizeof(dis));
dis[s]=1;_dfs(s);t=1;
for(int i=2;i<=n;i++)
if(dis[i]>dis[t]) t=i;
Max=dis[t];
}
int main()
{
int i,j,k,u,v,T,d,m;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
Max=0;
for(i=1;i<=n;i++) G[i].clear();
for(i=1;i<n;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
_finds();
_findt();
for(i=1;i<=m;i++){
scanf("%d",&d);
if(d<=Max) printf("%d
",d-1);
else printf("%d
",Max-1+(d-Max)*2);
}
}
return 0;
}