http://acm.hdu.edu.cn/showproblem.php?pid=4607
题目意思是在公园里(就是一棵树)遍历k个点所需最短路径。
这题用最长链做,可以选择两种方法:
1.一遍DFS(原谅本蒟蒻不会用这种方法写)
2.两遍BFS(本题用此方法)
我呢是先离线用BFS把树中的最长链求出来,那好,问题来了,为什么要求最长链?
题目要求遍历k个点最短路,那么把最长链求出来之后,分两种情况:
1.k<=L(最长链长度+1因为要求点,下同)这时只需输出k-1即可,这个不多证明。
2.k>L 输出(k-L)*2+L-1。
这样就得出了正确答案,时间比一遍DFS慢但是能过。
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
struct ppap{
int b,dis;
};
queue<ppap>q;bool vis[500001];
int nedge,n,m,dis,b,p[500001],head[500001],nex[500001];
void addedge(int a,int b){
nedge++;
p[nedge]=b;
nex[nedge]=head[a];
head[a]=nedge;
}
void bfs(int x){
memset(vis,true,sizeof vis);
while(!q.empty())q.pop();
ppap a;a.b=x;a.dis=0;vis[x]=false;
q.push(a);dis=0;b=x;
while(!q.empty()){
a=q.front();
q.pop();
if(a.dis>dis){dis=a.dis;b=a.b;}
int k=head[a.b];
while(k){
if(vis[p[k]]){
ppap jzq;jzq.dis=a.dis+1;jzq.b=p[k];
vis[p[k]]=false;
q.push(jzq);
}
k=nex[k];
}
}
}
int main()
{
int t;cin>>t;
for(;t;t--){
cin>>n>>m;
nedge=0;
memset(p,0,sizeof p);
memset(head,0,sizeof head);
memset(nex,0,sizeof nex);
for(int i=1;i<n;i++){
int x,y;cin>>x>>y;
addedge(x,y);
addedge(y,x);
}
bfs(1);
bfs(b);
dis++;
for(int i=1;i<=m;i++){
int k;cin>>k;
if(k<=dis)cout<<k-1<<endl;
else cout<<(k-dis)*2+dis-1<<endl;
}
}
return 0;
}