hdu 4607 树形dp 树的直径
题目大意:给你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>
#include<queue>
using namespace std;
#define inf 999999999
#define N 110000
struct node {
int u,v,next;
}bian[N*2];
int dis[N],head[N],yong;
void addedge(int u,int v) {
bian[yong].u=u;
bian[yong].v=v;
bian[yong].next=head[u];
head[u]=yong++;
}
int visit[N],n,m;
int spfa(int u) {
int i,v;
memset(visit,0,sizeof(visit));
memset(dis,0,sizeof(dis));
queue<int>q;
q.push(u);
visit[u]=1;
while(!q.empty()) {
v=q.front();
// printf("%d\n",v);
q.pop();
for(i=head[v];i!=-1;i=bian[i].next)
if(visit[bian[i].v]==0) {
dis[bian[i].v]=dis[v]+1;
visit[bian[i].v]=1;
q.push(bian[i].v);
}
}
int ma=1;
for(i=1;i<=n;i++)
if(dis[ma]<dis[i])
ma=i;
// printf("%d\n",dis[ma]);
return ma;
}
int main() {
int t,a,b,len,i;
scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&m);
yong=0;
memset(head,-1,sizeof(head));
for(i=1;i<n;i++) {
scanf("%d%d",&a,&b);
addedge(a,b);
addedge(b,a);
}
len=dis[spfa(spfa(1))]+1;
//printf("%d\n",len);
while(m--) {
scanf("%d",&a);
if(a<=len)
printf("%d\n",a-1);
else
printf("%d\n",len-1+(a-len)*2);
}
}
return 0;
}
浙公网安备 33010602011771号