题目大意:给你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; }