hdu4607Park Visit 树的直径

//给一棵双向树,数中边的权值为1,问对于这颗树中走k个节点的最短路径
//假设k小于这颗数的直径加1,那么走k个节点就没有反复的路,假设大于
//那么大于的节点都须要走两遍
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std ;
const int maxn = 100010 ;
int head[maxn] ;
int vis[maxn] ;
struct Edge
{
    int v ;
    int next ;
}edge[maxn*2] ;
int nedge ;
void addedge(int u , int v)
{
    edge[nedge].v = v ;
    edge[nedge].next = head[u] ;
    head[u] = nedge++ ;
    edge[nedge].v = u ;
    edge[nedge].next = head[v] ;
    head[v] = nedge++ ;
}
queue<int>que ;
int ma = 0 ;
int bfs(int st)
{
    while(que.size())que.pop() ;
    que.push(st) ;que.push(0) ;que.push(0) ;
    int pos ;
    while(que.size())
    {
        int u = que.front() ; que.pop() ;
        int step = que.front() ;que.pop() ;
        int pre = que.front() ; que.pop() ;
        if(step > ma)
        {
            ma = step ;
            pos = u ;
        }
        for(int i = head[u] ; i !=  -1 ;i = edge[i].next)
        {
            int v = edge[i].v ;
            if(v == pre)continue ;
            que.push(v);que.push(step+1);que.push(u) ;
        }
    }
    return pos ;
}
int main()
{
    int t ;
    scanf("%d" , &t) ;
    while(t--)
    {
        int n , m ;
        memset(head ,  -1 ,sizeof(head)) ;
        nedge = 0 ;
        scanf("%d%d" , &n , &m) ;
        for(int i = 1;i < n; i++)
        {
            int u  ,v ;
            scanf("%d%d" , &u , &v) ;
            addedge(u , v) ;
        }
        ma = 0 ;
        int pos = bfs(1) ;
        bfs(pos) ;
        while(m--)
        {
            int k ;
            scanf("%d" , &k) ;
            if(k <= ma+1)printf("%d\n" , k - 1) ;
            else printf("%d\n" , (k - (ma+1))*2+ma) ;
        }
    }
    return 0 ;
}















































posted @ 2016-04-22 18:01  blfshiye  阅读(133)  评论(0编辑  收藏  举报