题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4607
大意是,给你一个连通图(根据题意其实就是一棵树),N个点,问访问K个点最少需要走几条边。
是一个学弟问我的,很惭愧,真心不会,没做过类似的最短路径。
上网查了一下,才知道是求这个图的最大直径。
参考的是这个帖子,讲的还可以,代码也比较容易懂:http://www.cnblogs.com/0803yijia/p/3209371.html
代码粘一下吧,一模一样的,不过这个证明还真是挺意外的:
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int N=111111;
int m,n;
vector<int>vec[N];
struct node
{
int s;
int point;
};
int vis[N];
node bfs(int s)
{
memset(vis,0,sizeof(vis));
queue<node>q;
node tmp;
tmp.s=0;
tmp.point=s;
q.push(tmp);
vis[s]=1;
node Max;
Max.s=0;
while(!q.empty())
{
node now,temp;
now=q.front();
q.pop();
for(int i=0;i<vec[now.point].size();i++)
{
int v=vec[now.point][i];
temp.s=now.s+1;
temp.point=v;
if(!vis[v])
{
vis[v]=1;
if(Max.s<temp.s)
Max=temp;
q.push(temp);
}
}
}
return Max;
}
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 a,b;
scanf("%d %d",&a,&b);
vec[a].push_back(b);
vec[b].push_back(a);
}
node Max;
Max=bfs(1);
Max=bfs(Max.point);
for(int i=0;i<m;i++)
{
int k;
scanf("%d",&k);
if(k<=Max.s+1)
printf("%d\n",k-1);
else
printf("%d\n",(k-Max.s-1)*2+Max.s);
}
}
return 0;
}