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;
}



posted @ 2014-05-11 16:37  HYDhyd  阅读(165)  评论(0编辑  收藏  举报