题意简述:莱克尔和她的朋友到公园玩,公园很大也很漂亮。公园包含n个景点通过n-1条边相连。克莱尔太累了,所以不能去参观所有点景点。经过深思熟虑,她决定只访问其中的k个景点。她拿出地图发现所有景点的入口都很特殊。所以她想选择一个入口,并找到一条最短的路来参观k个景点。假设景点之间的距离为1。
输入数据:先输入测试用例数t,每个测试用例数据包括N和M,N为节点数,M为需要查询的上述的k(参观M个景点)。
输出数据:对于各个M,输出需要走的距离。
程序说明:函数dfs()用于计算树直径经过的节点数。其他都是套路。
这个程序在穷尽搜索的基础上做了一些剪枝。相比较而言,这个程序速度上会稍微慢一些。另外一种解法参见:HDU4607 Park Visit(解法二)。
AC的C++语言程序如下:
/* HDU4607 Park Visit */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int MAXN = 100000;
vector<int>tree[MAXN+1];
bool visit[MAXN];
int maxlen; // 树的最大直径
// DFS求最大树的直径
int dfs(int u)
{
visit[u] = true;
int max=0, lastmax=0, size;
size = tree[u].size();
for(int i=0; i<size; i++){
if(visit[tree[u][i]])
continue;
int temp = dfs(tree[u][i]);
if( temp + 1 > max){
lastmax = max ;
max = temp + 1;
}else if( temp + 1 > lastmax)
lastmax = temp + 1;
if( maxlen < max + lastmax)
maxlen = max + lastmax;
}
return max;
}
int main(void)
{
int t, n, m, u, v, k;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++)
tree[i].clear();
for(int i=1; i<n; i++) {
scanf("%d%d", &u, &v);
tree[u].push_back(v);
tree[v].push_back(u);
}
memset(visit, false, sizeof(visit));
maxlen = 0;
dfs(1);
while(m--) {
scanf("%d", &k);
if(k <= maxlen)
printf("%d\n", k-1);
else
printf("%d\n", maxlen + (k-maxlen-1)*2);
}
}
return 0;
}