題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4607
題目大意:給你n個點,n-1條邊,將圖連成一棵生成樹,問你從任意點爲起點,走k(k<=n)個點,至少需要走多少距離(每條邊的距離是1);
思路:樹形dp求樹的直徑r;
a:若k<=r+1 ,ans = k-1;
b:若k>=r+1,ans = r+(k-(r+1))*2;
#include "stdio.h"
#include "string.h"
#define N 110000
struct node
{
int x,y;
bool visit;
int next;
} edge[2*N];
int idx,head[N];
inline int MAX(int a,int b)
{
return a>b?a:b;
}
void Init()
{
idx=0;
memset(head,-1,sizeof(head));
}
void Add(int x,int y)
{
edge[idx].x=x;
edge[idx].y=y;
edge[idx].visit=false;
edge[idx].next=head[x];
head[x]=idx++;
}
int n;
int maxn[N],smaxn[N];
void DFS(int x)
{
int i,y;
maxn[x] = smaxn[x] = 0;
for(i=head[x]; i!=-1; i=edge[i].next)
{
y = edge[i].y;
if(edge[i].visit) continue;
edge[i].visit = edge[i^1].visit = true;
DFS(y);
if(maxn[y]+1>maxn[x])
{
smaxn[x] = maxn[x];
maxn[x] = maxn[y]+1;
}
else if(maxn[y]+1>smaxn[x])
smaxn[x] = maxn[y]+1;
}
}
int main()
{
int T,Q;
int i,j;
int x,y,k;
scanf("%d",&T);
while(T--)
{
Init();
scanf("%d%d",&n,&Q);
for(i=1; i<n; ++i)
{
scanf("%d %d",&x,&y);
Add(x,y);
Add(y,x);
}
DFS(1);
int D=0; //樹的直徑
for(i=1; i<=n; ++i)
D = MAX(D,maxn[i]+smaxn[i]);
D++;
while(Q--)
{
scanf("%d",&k);
if(k<=D)
printf("%d\n",k-1);
else
printf("%d\n",D-1+(k-D)*2);
}
}
return 0;
}